var async = require('async');
var CONFIG = require('../../../../common/config');
var CODE = require('../../../../common/code');
var YjxFavoriteModel = require('../../../../common/yjxMysql/mapping/YjxFavoriteModel');
var YjxTmplSetModel = require('../../../../common/yjxMysql/mapping/YjxTmplSetModel');
var YjxUniItemsModel = require('../../../../common/yjxMysql/mapping/YjxUniItemsModel');
var TgDesignDocModel = require('../../../../common/mysql/mapping/TgDesignDocModel');
var TgUserDocModel = require('../../../../common/mysql/mapping/TgUserDocModel');
var ItbTemplateModel = require('../../../../common/mysql/mapping/ItbTemplateModel');
var ItbTmplPageModel = require('../../../../common/mysql/mapping/ItbTmplPageModel');
var VideoDesignDocModel = require('../../../../common/mysql/mapping/VideoDesignDocModel');
var YjxUniUserDocModel = require('../../../../common/yjxMysql/mapping/YjxUniUserDocModel');
var YjxVideoUserDocModel = require('../../../../common/yjxMysql/mapping/YjxVideoUserDocModel');
var YjxPptUserDocModel = require('../../../../common/yjxMysql/mapping/YjxPptUserDocModel');
var YjxPptUserPageModel = require('../../../../common/yjxMysql/mapping/YjxPptUserPageModel');
var YjxDesignUserDocModel = require('../../../../common/yjxMysql/mapping/YjxDesignUserDocModel');
var YjxDesignUserPageModel = require('../../../../common/yjxMysql/mapping/YjxDesignUserPageModel');
var YjxDesignUserPcModel = require('../../../../common/yjxMysql/mapping/YjxDesignUserPcModel');
var YjxUserModel = require('../../../../common/yjxMysql/mapping/YjxUserModel');
var YjxVideoResModel = require('../../../../common/yjxMysql/mapping/YjxVideoResModel');
var TgTypeModel = require('../../../../common/mysql/mapping/TgTypeModel');
var YjxTradeOrderModel = require('../../../../common/yjxMysql/mapping/YjxTradeOrderModel');
var YjxPriceModel = require('../../../../common/yjxMysql/mapping/YjxPriceModel');
var YjxFormInfoModel = require('../../../../common/yjxMysql/mapping/YjxFormInfoModel');
var YjxFormTmplModel = require('../../../../common/yjxMysql/mapping/YjxFormTmplModel');
var YjxCustVideoUserDocModel = require('../../../../common/yjxMysql/mapping/YjxCustVideoUserDocModel');
var CommonUtil = require('../../../../common/util/CommonUtil');
var tg3Util = require('../../../routes/util/tg3Util'); // 此处为了方便兼容老的设计模板引用一键生成的工具类, tg3Util 不得引用当前工具类, 以免造成互相引用
var retUtil = require('./retUtil'); // 此处为了方便提取数据, 引用同级目录下的 retUtil, retUtil 不得引用当前工具类, 以免造成相互引用
var rpcFunc = require('../../../routes/rpcSrv/rpcFunc.js');
var luaUtil = require('../api4back/util/luaUtil');
var javaSearchProjectUtil = require('./javaSearchProjectUtil');
var superagent = require('superagent');
var VideoRenderLuadUtil = require('../../../../common/util/VideoRenderLuadUtil');
var YjxCustVideoUserDocModel = require('../../../../common/yjxMysql/mapping/YjxCustVideoUserDocModel');
var moment = require('moment');
// 分词模块
var Segment = require('node-segment').Segment;// 载入分词模块
var POSTAG = require('node-segment').POSTAG;// 载入词性接口
var segment = new Segment();// 创建实例
segment.useDefault();// 使用默认的识别模块及字典，载入字典文件需要1秒，仅初始化时执行一次即可


var documentUtil = (function () {

    function documentUtil() {

    }
    /**
     * 获取用户收藏表有无收藏该模板信息
     *
     * @author 毛凯
     * @date 2017-11-16
     *
     * @param   userId 用户标识
     * @param   tmplId 模板标识
     * @param   callback 回调
     *             err:出错原因
     *             res:0/1 0 标识用户未收藏过改模板， 1 标志用户收藏过该模板
     * */
    documentUtil.checkUserFavTmplState = function(userId,tmplId,callback){
        //查询用户收藏中有没有该收藏
        (new YjxFavoriteModel).checkUserFavTmplState(userId,tmplId,function(err,res){
            return callback(err, res);
        });
    };

    /**
     * 取消用户模板收藏
     * @author 毛凯
     * @date 2017-11-16
     *
     * @param   userId   用户标识
     * @param   tmplId   模板标识
     * @param   callback 回调
     *                 delErr:逻辑删除失败错误信息
     */
    documentUtil.delTmplToFav = function(userId,tmplId,callback){
        //逻辑删除用户收藏
        (new YjxFavoriteModel).delTmplToFav(userId,tmplId,function(delErr){
            return callback(delErr);
        });
    };
    /**
     * 取消用户模板收藏
     * @author 毛凯
     * @date 2017-11-16
     *
     * @param   collect    0 标识取消收藏, 1 标识收藏
     * @param   userId   用户标识
     * @param   tmplId   模板标识 修改数据库后变为(item_id)
     * @param   callback 回调
     *                 delErr:错误信息/成功返回NULL
     */
    documentUtil.setTmplCollectStatus_v1_0 = function(collect, userId, tmplId, callback){
        if(collect > 0) {
            // 1. 确认有无收藏过
            documentUtil.checkUserFavTmplState(userId,tmplId,function (err, result) {
                if(err) {
                    console.log('yjx/v1/document.js [setTmplCollectStatus_v1_0] checkUserFavTmplState error' + err);
                    return callback(err);
                }
                // 2. 如果收藏过， 则认为收藏成功， 直接返回
                if(result > 0){
                    return callback(null);
                }

                // 3. 如果没有收藏过， 则收藏,先查询模板Show_typ_id
                (new YjxUniItemsModel).findShowTypeId(tmplId,function(err, result){
                    if(err) {
                        console.log('yjx/v1/document.js [setTmplCollectStatus_v1_0]  addTmplToFav  error' + err);
                        return callback(err);
                    }

                    var stId = 0;
                    if(result && result.length > 0){
                        stId = result[0].st_id;
                    }

                    //4. 加入收藏表
                    var entity = new YjxFavoriteModel({
                        user_id : userId,
                        uni_item_id : tmplId,
                        show_type_id : stId
                    }) ;

                    entity.saveToDB(function(err,insertId){
                        if(err){
                            console.log("loginByThirdPlatform_v1_0 [saveToDB YjxThirdPartyUserModel] saveToDB" +err);
                        }
                        return callback(err);
                    });
                });
            });
            return;
        }

        // 取消收藏
        documentUtil.delTmplToFav(userId, tmplId, function (err, result) {
            if (err) {
                console.log('yjx/v1/document.js [setTmplCollectStatus_v1_0] delTmplToFav error' + err);
                return callback(err);
            }
            return callback(null);
        });
    };


    /**
     * 获取视频可用背景列表
     *
     * @author 李强
     * @date 2017-11-17
     * @param  userId 用户唯一标识
     * @param  docId  模版唯一标识
     * @param  pageNum: 页码
     * @param  pageSize : 页容量
     * @param withTotalPage : 0/1 是否获取总页数, 如需获取传递1, 否则传递0
     * @param callback 回调
     *              err 错误信息
     *              data 返回值
     * */

    documentUtil.getVideoUserDocBgList_v1_0 = function (userId,docId,pageNum,pageSize,withTotalPage,callback) {
        //用userId和docId获取视频作品的尺寸
        var entity = new YjxVideoUserDocModel();
        entity.getVideoSize(userId,docId,function(err,size){
            if(err){
                return callback(err,{});
            }
            if(!size || size.length == 0){
                return callback("未找到对应作品的尺寸信息",{});
            }

            //根据视频尺寸获取相应的可替换视屏背景的sizeId
            entity.getVideoBgsize(size[0].w,size[0].h,function(err,sizeIds){
                if(err){
                    return callback(err,{});
                }
                if(!sizeIds || sizeIds.length == 0){
                    return callback("未找到对应作品的尺寸信息",{});
                }

                //通过获取到尺寸id集合获取对应可用视频背景的模版列表
                entity.getVideoBgDesignList(sizeIds,pageNum,pageSize,function(err,lists){
                    if(err){
                        return callback(err,{});
                    }
                    if(!lists || lists.length == 0){
                        return callback(null,{list:[]});
                    }

                    var data = {};
                    data.list = lists;
                    if(withTotalPage) {
                        entity.getVideoBgDesignListCut(sizeIds, pageNum, pageSize,function(err, count){
                            if (err) {
                                return callback(err, {});
                            }
                            data.totalPage = Math.floor((count-1)/pageSize)+1;
                            return callback(err, data);
                        })
                    }else{
                        return callback(err, data);
                    }
                })
            })
        })
    };


    /**
     * 新增/替换可用视频背景
     *
     * @author 李强
     * @date 2017-11-20
     * @param userId: 用户唯一标识
     * @param docId : 统一作品id
     * @param bgId: 背景模版唯一标识
     * @param callback 回调
     *              err 错误信息
     *              data 返回值
     * */

    documentUtil.setVideoBG_v1_0 = function (userId,bgId,docId,callback) {
        var item = new YjxUniItemsModel({
            uni_item_id:bgId,
            del_flg : 0
        });
        //获取当前视频背景模版信息
        item.findFromDB(function (findDesignErr, results) {
            if (findDesignErr || !results || results.length <= 0) {
                return callback(findDesignErr || '该模板不存在或已下架', null);
            }
            var designId = results[0].item_id;
            //判断作品类型,如果是视频作品判断是否有背景id,没有创建 ,有则替换
            var entity = new YjxUniUserDocModel();
            entity.checkUniUserDocType(docId,function (checkErr, typeInfo) {
                if (checkErr) {
                    return callback(checkErr, null);
                }
                if(typeInfo.video_bg_id){
                    var video_bg_id = typeInfo.video_bg_id; // 子表 id
                    //替换(先删除再新增)
                    documentUtil.deleteDesignUserDoc(userId,video_bg_id,function(err){
                        if(err){
                            return callback(err,{});
                        }
                        documentUtil.enptyVideoCombRes_v1_0(userId,docId,function(updateErrMsg){
                            if(updateErrMsg){
                                return callback(updateErrMsg,{});
                            }
                            documentUtil.addDesignDoc(docId,designId,userId,callback);
                        })
                    })
                }else{
                    documentUtil.enptyVideoCombRes_v1_0(userId,docId,function(updateErrMsg){
                        if(updateErrMsg){
                            return callback(updateErrMsg,{});
                        }
                        documentUtil.addDesignDoc(docId,designId,userId,callback);
                    })
                }
            })
        });
    };


    /**
     * 新增可用视频背景
     *
     * @author 李强
     * @date 2017-11-20
     * @param userId: 用户唯一标识
     * @param docId : 模版唯一标识
     * @param bgId: 背景模版唯一标识  tg_design_doc  designId
     * @param callback 回调
     *              err 错误信息
     *              data 返回值
     * */
    documentUtil.addDesignDoc =  function(docId,bgId,userId,callback){
        //通过bgId获取模板核心数据
        var type_id = 1030;
        tg3Util.getTgAndFineTuneInfoOfDesign(type_id, bgId, function (getDesignErr01, data01) {
            if(getDesignErr01) {
                return callback(getDesignErr01, null);
            }
            if(data01 && data01.constructor) {
                data01.coreStructure = retUtil.safe_parser_JSON_string(data01.coreStructure);
            }
            //新增设计作品文档
            documentUtil.newDesignUserDoc(userId, docId, bgId, JSON.stringify(data01), function(err02,results02){
                if(err02) {
                    return callback(err02, null);
                }
                return callback(err02,results02);
            })
        });
    };

    /**
     * 清空视频背景
     * @author 李强
     * @date 2017-11-20
     * @param userId 用户唯一标识
     * @param docId  模版唯一标识
     * @param callback 回调
     *              err 错误信息
     *              data 返回值
     * */

    documentUtil.clearVideoBG_v1_0 = function (userId,docId,callback) {
        //判断作品类型,如果是视频作品判断是否有背景id,
        var entity = new YjxUniUserDocModel();
        entity.checkUniUserDocType(docId,function (checkErr, typeInfo) {
            if (checkErr) {
                return callback(checkErr, null);
            }
            if (typeInfo.video_bg_id) {
                var video_bg_id = typeInfo.video_bg_id; // 子表 id
                //删除
                documentUtil.enptyVideoCombRes_v1_0(userId,docId,function(updateErrMsg){
                    if(updateErrMsg){
                        return callback(updateErrMsg,{});
                    }
                    documentUtil.deleteDesignUserDoc(userId, video_bg_id, function (err) {
                        return callback(err, {});
                    })
                })
            } else {
                return callback("未检索到对应背景作品文档", {});
            }
        })
    };


    /**
     * 修改视频背景
     * @author 李强
     * @date 2017-11-20
     * @param userId  用户唯一标识
     * @param docId  模版唯一标识
     * @param bgString: 背景核心数据
     * @param callback 回调
     *              err 错误信息
     *              data 返回值
     * */

    documentUtil.updateVideoDocBg_v1_0 = function (userId,docId,bgString,callback) {
        //判断作品类型,如果是视频作品判断是否有背景id
        var entity = new YjxUniUserDocModel();
        entity.checkUniUserDocType(docId,function (checkErr, typeInfo) {
            if (checkErr) {
                return callback(checkErr, null);
            }
            if (typeInfo.video_bg_id) {
                var video_bg_id = typeInfo.video_bg_id; // 子表 id
                //修改
                documentUtil.enptyVideoCombRes_v1_0(userId,docId,function(updateErrMsg) {
                    if (updateErrMsg) {
                        return callback(updateErrMsg, {});
                    }
                    documentUtil.updateDesignUserDoc(userId, docId, bgString, function (updateErr, docInfo) {
                        if(updateErr) {
                            return callback(updateErr, null);
                        }
                        return callback(updateErr, docInfo);
                    });
                });
            } else {
                return callback("未检索到对应背景作品文档", {});
            }
        })
    };

    /**
     * 清空 合成视频资源id
     * @author 李强
     * @date 2017-12-25
     * @param userId 用户唯一标识
     * @param docId  统一用户作品id
     * @param callback 回调
     *              err 错误信息
     * */
    documentUtil.enptyVideoCombRes_v1_0 = function (userId,docId,callback) {
        var entity = new YjxVideoUserDocModel();
        entity.enptyVideoCombRes_v1_0(userId,docId,function(err){
            callback(err);
        })
    };


    /**
     * 获取视频背景信息
     * @author 李强
     * @date 2017-11-20
     * @param userId 用户唯一标识
     * @param docId  模版唯一标识
     * @param callback 回调
     *              err 错误信息
     *              data 返回值
     * */

    documentUtil.getVideoDocBgInfo_v1_0 = function (userId,docId,callback) {
        //判断作品类型,如果是视频作品判断是否有背景id
        var entity = new YjxUniUserDocModel();
        entity.checkUniUserDocType(docId,function (checkErr, typeInfo) {
            if (checkErr) {
                return callback(checkErr, null);
            }
            var bgId;
            if (typeInfo.video_bg_id) {
                var video_bg_id = typeInfo.video_bg_id; // 子表 id
                //获取设计作品的核心数据
                documentUtil.getDesignUserDocContent(video_bg_id, userId, function (getDocErr, data) {
                    if (getDocErr) {
                        return callback(getDocErr, null);
                    }
                    if(data.constructor) {
                        data.coreStructure = retUtil.safe_parser_JSON_string(data.coreStructure);
                    }
                    data.bgId= bgId;
                    return callback(getDocErr, data)
                });
            } else {
                return callback("未检索到对应背景作品文档", {});
            }
        })

    };




    /***
     * 获取指定范围模板组内模板列表
     *
     * @author 王俊
     * @date 2017-11-16
     *
     * @param setIds 模板组 id 数组
     * @param tmplTypes 0 代表普通模板, 10 代表 vip 模板, 不传默认为 [0], 标记只获取普通模板
     * @param pageNum 页码
     * @param pageSize 页容量
     * @param withTotalPage 是否需要总页数
     * @param durations 视频时长
     * @param industrySetIds 视频行业
     * @param sizeIds 视频尺寸
     * @param callback 回调
     *          err: 查询出错
     *          data:{
     *              list : [{
     *                      "id":1999,
     *                      "opType":1,         // 业务分类 暂定如下: 1 竖屏类型(单页/印品), 2 视频类型, 3 ppt 类型
     *                      "typeDesc":"优惠券",
     *                      "name":"创意少儿书法培训优惠券",
     *                      "thumb":"http://itbour-generate.oss-cn-hangzhou.aliyuncs.com/image/U408535/2017/11/07/143418993_uEuOZh77Qw0kIiwtXmCQ/0.jpg",
     *                      "useCounts":3697,
     *                      "w":1537,
     *                      "h":496,
     *                      "author":"李国梅",
     *                      "time":"2017-11-05 13:42:41",
     *              }],
     *              totalPage : 1   // 如果需要请求, 则返回此字段
     *          }
     */
    documentUtil.getTmplSetContentList_v1_0 = function(setIds, tmplTypes, pageNum, pageSize, withTotalPage,durations,industrySetIds,sizeIds, callback) {
        var param={
            showTypes : [],
            keyword : [],
            setIds : setIds,
            orderBy : 4,
            pageNum : pageNum,
            pageSize : pageSize,
            withTotalPage : withTotalPage,
            tmplTypes : tmplTypes,
            durations : durations,
            industrySetIds:industrySetIds,
            sizeIds: sizeIds
        };
        luaUtil.searchUniItemsFromRedis(param,callback);
//        // 使用java搜索缓存
//        javaSearchProjectUtil.searchUniItemsFromJavaRedis(param,function (error, List) {
//            if(error){
//                console.log("luaUtil.js [searchUniItemsFromJavaRedis] err"+error);
//                return callback("没有获取到数据",{});
//            }
//            if(!List){
//                return callback("没有获取到数据",{});
//            }
//            return callback(null,List.data);
//        });
        //// 使用搜索缓存
        //luaUtil.searchUniItemsFromRedis([], [], setIds, 4/*按 order, updateTime 排序*/, pageNum, pageSize, function (error, data) {
        //    return callback(error, data);
        //});

        // // 1. 获取列表
        // var entity = new YjxTmplSetModel();
        // entity.getTmplSetsContentList(setIds, pageNum, pageSize,function (getListErr, list) {
        //     if(getListErr) {
        //         return callback(getListErr, null);
        //     }
        //     // 2. 不需要总页数, 直接返回
        //     if(!withTotalPage) {
        //         return callback(getListErr, {list:list});
        //     }
        //     // 3. 需要取总页数查询总页数
        //     entity.getTmplSetsContentListCnt(setIds, function (getCntErr, count) {
        //         if(getCntErr) {
        //             return callback(getCntErr, null);
        //         }
        //         var totalPage = Math.floor((count-1)/pageSize)+1;
        //         return callback(getCntErr, {list:list, totalPage : totalPage});
        //     });
        // })
    };


    /**
     * 查询模板预览详情
     *
     * @author 王俊
     * @date 2017-11-17
     *
     * @param uniId 统一模板标识
     * @param needSetName 是否需要获取模板组名称
     * @param callback  回调
     *          err: 查询失败
     *          data: {
     *                       "id":4903,                  // 模板唯一标识
     *                       "opType":1,                 // 业务分类 暂定如下: 1 竖屏类型(单页/印品), 2 视频类型, 3 ppt 类型
     *                       "name":"欢度国庆",           // 模板名称
     *                       "image": {                  // 当模板使用图片展示时返回此字段, 若模板需要使用视频展示时此字段为空
     *                           "thumbs":[              // 展示缩略图数组, 如有多页按数组顺序显示
     *                             "http://itbour-generate.oss-cn-hangzhou.aliyuncs.com/image/U30330/2016/11/06/091954617_IqjCfwBAzWz7I683nMRf/0.jpg"
     *                           ],
     *                           "w" : 720,
     *                           "h" : 1280
     *                       },
     *                       "video":{                  // 当模板使用视频展示时返回此字段, 若模板需要使用图片展示时此字段为空
     *                           "thumbs":[             // 视频缩略图数组, 如有多个, 只取第一个显示
     *                             "http://itbour-generate.oss-cn-hangzhou.aliyuncs.com/image/U30330/2016/11/06/091954617_IqjCfwBAzWz7I683nMRf/0.jpg"
     *                           ],
     *                           "videoUrl" : "http://itbour-generate.oss-cn-hangzhou.aliyuncs.com/image/U30330/2016/11/06/091954617_IqjCfwBAzWz7I683nMRf/0.mp4",
     *                           "duration" : 100,           // 视频时长, 单位:秒
     *                           "fileSize" : 4093200,       // 视频内存大小, 单位: Byte, 前端计算使用1000做进制转换, 避免出现流量显示与使用不一致的情况
     *                           "w":720,
     *                           "h":1280,
     *                       }
     *          }
     */
    documentUtil.getTmplDetail_v1_0 = function (uniId, needSetName, callback) {
        // 查询模板每页数据,
        (new YjxUniItemsModel()).getTemplatePreviewInfo(uniId, function (error, results) {
            // 获取模板页数据, 如果一页都查不到则该模板状态有问题
            if(error || !results || results.length <=0) {
                return callback(error || '该模板已下架', null);
            }
            // 重组模板数据
            var data = {};
            for (var i=0; i<results.length; i++) {
                var page = results[i];
                // 初始化跟属性
                if(!data.id) {
                    data.id = page.id;
                    data.opType = page.opType;
                    data.useCounts = page.useCounts;
                    data.name = page.NAME;
                    data.vip = page.vip;
                    data.xmPrice = page.xmPrice;
                    if (Number(page.opType) === 2 && !data.video) {
                        data.video = {
                            thumbs : [],
                            videoUrl : page.videoUrl,
                            duration : page.duration,
                            fileSize : page.fileSize,
                            w : page.w,
                            h : page.h
                        };
                    } else if (Number(page.opType) !== 2 && !data.image) {
                        data.image = {
                            thumbs : [],
                            w : page.w,
                            h : page.h
                        };
                    }
                }
                // 塞入预览图
                if(page.thumb) {
                    Number(page.opType) === 2
                        ? data.video.thumbs.push(page.thumb)
                        : data.image.thumbs.push(page.thumb);
                }
                var replaceTextCnt = 0;
                var replaceImageCnt = 0;
                var replaceVideoCnt = 0;
                if (Number(page.opType) === 2) {
                    //计算模板可输入文本个,数图片个数,小视屏个数
                    var object = JSON.parse(page.data);
                    var children = object.root.children;
                    if (children && children.length > 0) {
                        for (var j = 0; j < children.length; j++) {
                            var type = children[j].type;
                            var relation = children[j].relations;
                            if (type == 1 && relation && relation.length > 0) {
                                replaceTextCnt++;
                            }
                            if (type == 2 && relation && relation.length > 0) {
                                replaceImageCnt++;
                            }
                            if (type == 7 && relation && relation.length > 0) {
                                replaceVideoCnt++;
                            }
                        }
                    }
                }
                data.replaceTextCnt = replaceTextCnt;
                data.replaceImageCnt = replaceImageCnt;
                data.replaceVideoCnt = replaceVideoCnt;
            }
            if(!needSetName) {
                return callback(error, data);
            }
            // 按需获取模板组名称
            var entity = new YjxUniItemsModel();
            entity.getUniItemTmplSets(uniId, function (error, tmplSets) {
                if (tmplSets && tmplSets.length) data.setName = tmplSets[0].title || '国际广告';
                return callback(error, data);
            });
        });
    };

    /**
     * 获取模板核心数据
     *
     * @author 王俊
     * @date 2017-11-17
     *
     * @param uniId     统一模板唯一标识
     * @param callback  回调
     *          error: 错误
     *          data: {
     *              tmplId : 统一模板唯一标识,
     *              opType :  业务分类, 暂定如下: 1 竖屏(单页/印品等)  2 视频  3 PPT,
     *              docString: 参见接口: http://114.55.172.253:7000/project/11/interface/api/43
     *          }
     *          注意: docString 此处仍为各类型对象, 便于使用, 路由层再转换为 json 字符串
     */
    documentUtil.getTmplDocContent_v1_0 = function (uniId, callback) {

        // 1. 查询模板分类
        var uniEntity = new YjxUniItemsModel({
            uni_item_id : uniId,
            del_flg : 0
        });
        uniEntity.findFromDB(function (findTmplErr, results) {
            if(findTmplErr || !results || results.length <=0) {
                return callback(findTmplErr || '该模板不存在或已下架', null);
            }
            // 分类查询子项内容
            var tmplDoc = results[0];
            tmplDoc.item_type = Number(tmplDoc.item_type);
            var retData = {
                tmplId : tmplDoc.uni_item_id
            };
            // 10 查询单页数据
            if (tmplDoc.item_type === 10) {
                tg3Util.getTgAndFineTuneInfoOfDesign(tmplDoc.type_id, tmplDoc.item_id, function (getDesignErr, data) {
                    if(getDesignErr || !data) {
                        return callback(getDesignErr || '模板不存在或已下架', null);
                    }
                    if(data.constructor) {
                        data.coreStructure = retUtil.safe_parser_JSON_string(data.coreStructure);
                    }
                    retData.opType = 1;
                    retData.docString = data;
                    return callback(getDesignErr, retData);
                });
            }
            // 20 查询 ppt 数据
            else  if (tmplDoc.item_type === 20) {
                documentUtil.getPPTTmplDocContent(tmplDoc.item_id, function (getPPTErr, data) {
                    if (getPPTErr) {
                        return callback(getPPTErr, null);
                    }
                    retData.opType = 3;
                    retData.docString = data;
                    return callback(getPPTErr, retData);
                });
            }
            // 30 查询视频数据
            else  if (tmplDoc.item_type === 30) {
                documentUtil.getVideoTmplDocContent(tmplDoc.item_id, function (getVideoErr, data) {
                    if(getVideoErr) {
                        return callback(getVideoErr, null);
                    }
                    retData.opType = 2;
                    retData.docString = data;
                    return callback(getVideoErr, retData);
                });
            } else  {
                return callback('该模板不存在', null);
            }
        });
    };

    /**
     * 获取模板核心数据(DEBUG, 不论模板是否发布)
     *
     * @author 王俊
     * @date 2017-11-17
     *
     * @param itemId     子表 id
     * @param itemType    模版类型:10:单页, 20:PPT, 30:视频, 暂不支持 ppt
     * @param callback  回调
     *          error: 错误
     *          data: {
     *              tmplId : 统一模板唯一标识,
     *              opType :  业务分类, 暂定如下: 1 竖屏(单页/印品等)  2 视频  3 PPT,
     *              docString: 参见接口: http://114.55.172.253:7000/project/11/interface/api/43
     *          }
     *          注意: docString 此处仍为各类型对象, 便于使用, 路由层再转换为 json 字符串
     */
    documentUtil.getTmplDocInfo_for_debug = function (itemId, itemType, callback) {

        // 1. 查询模板分类
        var uniEntity = new YjxUniItemsModel({
            item_id : itemId,
            item_type : itemType,
            del_flg : 0
        });
        uniEntity.findFromDB(function (findTmplErr, results) {
            if(findTmplErr || !results || results.length <=0) {
                return callback(findTmplErr || '该模板不存在', null);
            }
            // 分类查询子项内容
            var tmplDoc = results[0];
            tmplDoc.item_type = Number(tmplDoc.item_type);
            var retData = {
                tmplId : tmplDoc.uni_item_id
            };
            if (itemType !== 30) {
                return callback('暂不支持的模板类型', null);
            }
            // 30 查询视频数据
            documentUtil.getVideoTmplDocContent_for_debug(tmplDoc.item_id, function (getVideoErr, data) {
                if(getVideoErr) {
                    return callback(getVideoErr, null);
                }
                retData.opType = 2;
                retData.docString = data;
                return callback(getVideoErr, retData);
            });
        });
    };
    /**
     * 获取作品核心数据
     *
     * @author 王俊
     * @date 2017-11-17
     *
     * @param uniId     作品唯一标识
     * @param userId    用户唯一标识
     * @param callback  回调
     *          data: {
     *              docId : 作品唯一标识
     *              opType :  业务分类, 暂定如下: 1 竖屏(单页/印品等)  2 视频  3 PPT,
     *              docString: 参见接口: http://114.55.172.253:7000/project/11/interface/api/43
     *          }
     *          注意: docString 此处仍为各类型对象, 便于使用, 路由层再转换为 json 字符串
     */
    documentUtil.getUserDocContent_v1_0 = function(uniId, userId, callback){

        var entity = new YjxUniUserDocModel();
        entity.checkUniUserDocType(uniId,function (checkErr, typeInfo) {
            if(checkErr) {
                return callback(checkErr, null);
            }
            var docId = typeInfo.doc_id; // 子表 id
            var docType = Number(typeInfo.doc_type);    // 子表类型, 10 竖屏, 20 ppt, 30 视频
            var retData = {
                docId : typeInfo.uni_doc_id
            };
            // 兼容 web, 获取模板统一 id
            var uniItem = new YjxUniItemsModel({
                item_type : docType,
                item_id : typeInfo.doc_design_id
            });
            uniItem.findFromDB(function (findDesignErr, results) {
                if(findDesignErr) {
                    return callback(checkErr, null);
                }
                if(results && results.length >0) {
                    retData.tmplId = results[0].uni_item_id;
                }

                // 竖屏作品
                if(docType === 10) {
                    documentUtil.getDesignUserDocContent(docId, userId, function (getDocErr, data) {
                        if (getDocErr) {
                            return callback(getDocErr, null);
                        }
                        if(data.constructor) {
                            data.coreStructure = retUtil.safe_parser_JSON_string(data.coreStructure);
                        }
                        retData.docString = data;
                        retData.opType = 1; // 前端业务逻辑, 竖屏 为 1
                        return callback(getDocErr, retData)
                    })
                }
                // ppt 作品
                else if(docType === 20) {
                    documentUtil.getPPTUserDocContent(docId, userId, function (getPPTDocErr, data) {
                        if(getPPTDocErr) {
                            return callback(getPPTDocErr, null);
                        }
                        retData.docString = data;
                        retData.opType = 3; // 前端业务流程
                        return callback(getPPTDocErr, retData);
                    })
                }
                // 视频作品
                else if (docType === 30) {
                    documentUtil.getVideoUserDocContent(docId, userId, function (getVideoErr, data) {
                        if(getVideoErr) {
                            return callback(getVideoErr, null);
                        }
                        retData.docString = data;
                        retData.opType = 2; // 前端业务逻辑, 视频为2
                        return callback(getVideoErr, retData);
                    });
                }

            });
        })
    };
    /**
     * todo 复制自老接口, 待测
     * 获取用户设计作品核心数据
     *
     * @author 王俊
     * @date = 2017-11-17
     *
     * @param docId 竖屏作品唯一标识
     * @param userId 用户唯一标识
     * @param callback 回调
     *          err: 获取数据失败
     *          data: 设计核心数据模型, 参见接口: http://114.55.172.253:7000/project/11/interface/api/43
     */
    documentUtil.getDesignUserDocContent = function (docId, userId, callback) {
        var entity = new YjxDesignUserDocModel({
            doc_id: docId,
            user_id : userId,
            del_flg:0
        });
        // 获取视频坑位置
        entity.getViewBgContentVideoFrame(docId, function (error, videoFrame) {
            entity.getTgAndFineTuneInfoOfUserDoc(function(error, data) {
                if (error || !data) {
                    return callback(error || '该文档不存在或已删除', null);
                }
                // 如果存在视频坑, 则传递视频坑
                if(videoFrame) {
                    data.videoFrame = videoFrame;
                }
                // 查看微调数据，如果存在则返回，
                if(data.textObjects && data.textObjects.length>0){
                    return callback(null ,data);
                }
                // 如果微调数据不存在则重新获取
                else{
                    documentUtil.getUserDesignDocFineTuneInfo(data.design_id, function (getFineTuneErr, fineTuneInfo, coreStructure) {
                        if(getFineTuneErr) {
                            return callback(getFineTuneErr, null);
                        }
                        // 设置微调数据
                        data.textObjects = fineTuneInfo;
                        data.coreStructure = coreStructure;
                        return callback(getFineTuneErr, data);
                    });
                }
            });
        });
    };
    /**
     * todo 复制自老接口, 待测
     * 获取用户竖屏作品微调数据
     *
     * @author 王俊
     * @date 2017-11-18
     *
     * @param designId 竖屏作品对应模板的 id
     * @param callback
     *          error: 获取失败
     *          textObjects: 微调信息
     *          coreStructure: 提纲核心数据
     */
    documentUtil.getUserDesignDocFineTuneInfo = function (designId, callback) {
        // 如果微调数据不存在，则获取其design的微调数据
        var entity2 = new TgDesignDocModel({
            design_id:data.designId,
            del_flg:0
        });
        entity2.findFromDB(function(error,items) {
            if (error|| !items || items.length===0) {
                console.log(error);
                return callback(error,null);
            }
            var designDoc = items[0];
            if(designDoc.finetune_data && designDoc.finetune_data.length>0){
                // 设置微调数据
                data.textObjects = designDoc.finetune_data;
                return callback(null ,data);
            }else{
                // 如果design微调数据不存在，则创建并更新到design中
                //tg3Util.createFineTuneInfoOfDesign(data.designId,  function(error, fineTuneInfo, coreStructure){
                tg3Util.createFineTuneInfoOfDesignByHTTP(designId,  function(error, fineTuneInfo, coreStructure){// replace by jackLiu20180505 使用image服务来处理
                    if(!fineTuneInfo){
                        console.log('无法根据模版创建微调数据');
                        return callback('无法根据模版创建微调数据', null);
                    }
                    return callback(error ,fineTuneInfo, coreStructure);
                });
            }
        },0,1);
    };

    /**
     * 获取 ppt 模板文档核心数据
     *
     * @deprecated 一键秀暂不支持 PPT
     *
     * @author 王俊
     * @date 2017-11-17
     *
     * @param tmplId ppt 模板表主键
     * @param callback 回调
     *          error: 查询失败
     *          data: 参见接口 : http://114.55.172.253:7000/project/11/interface/api/43
     *
     * */
    documentUtil.getPPTTmplDocContent = function (tmplId, callback) {
        // 检索document
        var entity  = new ItbTemplateModel({
            tmpl_id: tmplId,
            del_flg: 0
        });
        entity.findFromDB(function (findTmplErr, items) {
            if (findTmplErr || !items || items.length <=0 ) {
                console.log('yjx/v1/util/documentUtil.js [getPPTTmplDocContent] findTmplErr: '+findTmplErr);
                return callback(findTmplErr || '该模板已下架', null);
            }
            var tmplEntity = items[0];
            // 检索到文档时
            var ver = tmplEntity.ver;
            var base_doc_id = tmplEntity.base_tmpl_id;
            var pageEntity = new ItbTmplPageModel({
                tmpl_id:tmplId,
                backup_flg : 0,
                del_flg:0
            });

            // 检索pages
            pageEntity.findFromDB(function (getPagesErr, pages) {
                if (getPagesErr || !pages || pages.length === 0) {
                    console.log('yjx/v1/util/documentUtil.js [getPPTTmplDocContent] findTmplPageErr: '+getPagesErr);
                    return callback(getPagesErr, null)
                }
                // 重新组织页数据
                documentUtil.processPPTPages(pages, function (processPageErr, results) {
                    if(processPageErr) {
                        return callback(processPageErr, null);
                    }
                    var retData = {
                        doc_id:tmplEntity.tmpl_id,
                        doc_name: '',
                        tmpl_name : tmplEntity.tmpl_name,
                        base_doc_id:base_doc_id,
                        ver:ver,
                        max_id:0,// TODO
                        pages:results
                    };
                    return callback(processPageErr, retData);
                });
            });
        });
    };

    /**
     * todo 复制自老接口, 待测
     * 获取 ppt 作品文档核心数据
     *
     * @deprecated 一键秀暂不支持 PPT
     *
     * @author 王俊
     * @date 2017-11-17
     *
     * @param docId ppt 作品表主键
     * @param userId 用户唯一标识
     * @param callback 回调
     *          error: 查询失败
     *          data: 参见接口 : http://114.55.172.253:7000/project/11/interface/api/43
     *
     * */
    documentUtil.getPPTUserDocContent = function (docId, userId, callback) {
        // 检索document
        var entity = new YjxPptUserDocModel({
            doc_id: docId,
            del_flg: 0
        });
        entity.findFromDB(function (getDocErr, items) {
            if(getDocErr || !items || items.length <=0) {
                return callback(getDocErr || '获取作品失败', null);
            }
            var docEnity = items[0];
            // 检索到文档时
            var ver = docEnity.ver;
            var base_doc_id = docEnity.base_doc_id;
            var pageEntity = new YjxPptUserPageModel({
                doc_id:docId,
                del_flg:0
            });
            // 检索pages
            pageEntity.getPageInfoAndTmplRep(function (getPageErr, pages) {
                if (getPageErr) {
                    return callback(getPageErr, null);
                }
                // 重新组织文档结构
                documentUtil.processPPTPages(pages, function (processPageErr, results) {
                    if(processPageErr) {
                        return callback(processPageErr, null);
                    }
                    var retData = {
                        doc_id:docEnity.doc_id,
                        doc_name: docEnity.doc_name,
                        base_doc_id:base_doc_id,
                        ver:ver,
                        max_id:0,// TODO
                        pages:results
                    };
                    return callback(processPageErr, retData);
                });
            });
        });

    };

    /**
     * 组织 PPT 文档(模板/作品) 一页数据
     *
     * @deprecated 一键秀暂不支持 PPT
     *
     * @author 王俊
     * @date 2017-11-17
     *
     * @param pageItems 待组织页数据的数组
     * @param callback 回调
     *          error: 组织失败
     *          data: 组织后的 ppt 页数据
     */
    documentUtil.processPPTPages = function (pageItems, callback) {
        pageItems = pageItems||[];
        pageItems.sort(function(a,b){
            return a.page_index-b.page_index
        });
        // 组织pages数据
        var pagesData=[];
        for (var i in pageItems) {
            var pageItem = pageItems[i];
            // if (backup_flg == 0) {// 只获取普通页
            //     if (Number(pageItem.backup_flg)>0) continue;// 跳过保留页
            // }
            var strJsonRep = (pageItem.replaces || '[]').replace(/\n/g,'\\n');// page的replaces,处理Text对象的换行符
            var imgMask = [];
            var strTmplRep = '[]';
            if (pageItem.tmpl_page_id ) {
                // 用户文档
                strTmplRep = (pageItem.tmpl_replaces || '[]').replace(/\n/g,'\\n');// 模版的replaces
            } else {
                // 模版本身
                strTmplRep = strJsonRep;
            }
            var jsonTmplRep = JSON.parse(strTmplRep);
            if (jsonTmplRep && jsonTmplRep.length > 0) {
                for (var n in jsonTmplRep) {// 解析replaces
                    var repGrp = jsonTmplRep[n];
                    for (var k in repGrp.value){
                        var repItem = repGrp.value[k];
                        repItem.ct = Number(repItem.ct);
                        // CLASS_TYPE_SJGReplaceItemImage
                        if (repItem.ct === 805) {
                            var tmpData = {
                                id: repItem.id,
                                mask: repItem.mask || {}
                            };
                            imgMask.push(tmpData);
                            // CLASS_TYPE_SJGReplaceItemImageText / CLASS_TYPE_SJGReplaceItemImageText2
                        } else if (repItem.ct === 806 || repItem.ct === 812) {
                            var tmpData = {
                                id: repItem.image.id,
                                mask: repItem.image.mask || {}
                            };
                            imgMask.push(tmpData);
                        }
                    }
                }
            }

            var tmplPageId = '';
            // if (tmpl_flg == 0) {
            //     tmplPageId = pageItem.base_page_id;
            // }
            var pageData = {
                page_id: pageItem.page_id,
                base_page_id: tmplPageId,
                thumb: pageItem.thumb_s || '',
                page_index: pageItem.page_index,
                content: JSON.parse(strJsonRep) || '',
                img_mask: imgMask
            };
            pagesData.push(pageData);
        }
        // // 组织data数据
        // var retData = {
        //     doc_id:doc_id,
        //     // doc_name: (tmpl_flg == 0) ? (doc_name || '') : '',
        //     doc_name: doc_name,
        //     base_doc_id:base_doc_id,
        //     ver:ver,
        //     max_id:0,// TODO
        //     pages:pagesData
        // };
        return callback(null, pagesData);
    };

    /**
     * 获取视频模板文档内容
     *
     * @author 王俊
     * @date 2017-11-17
     *
     * @param designId 视频模板表唯一标识
     * @param callback  回调
     *          error: 查询失败
     *          data: 参见接口 : http://114.55.172.253:7000/project/11/interface/api/43
     */
    documentUtil.getVideoTmplDocContent = function (designId, callback) {

        var entity = new VideoDesignDocModel({
            design_id : designId,
            publish : 1,
            del_flg : 0
        });
        entity.getDesignDocInfo(designId, function (getVideoErr, designRow) {
            if(getVideoErr || !designRow) {
                return callback(getVideoErr || '该模板不存在或已下架', null);
            }
            // 模板发布前已预览, 故不需要排版
            var ret = {
                designId : designRow.design_id,
                designNm : designRow.design_name,
                productId : 0,
                productNm : '',
                pageWidth : designRow.width,
                pageHeight : designRow.height,
                sceneThumbs : retUtil.safe_parser_JSON_string(designRow.thumbs) || [],
                coreStructure : retUtil.safe_parser_JSON_string(designRow.tg_data)
            };
            return callback(null, ret);
        });
    };
    /**
     * 获取视频模板文档内容 debug
     *
     * @author 王俊
     * @date 2017-12-27
     *
     * @param designId 视频模板表唯一标识
     * @param callback  回调
     */
    documentUtil.getVideoTmplDocContent_for_debug = function (designId, callback) {

        var entity = new VideoDesignDocModel({
            design_id : designId,
            publish : 1,
            del_flg : 0
        });
        entity.getDesignDocInfo_for_debug(designId, function (getVideoErr, designRow) {
            if(getVideoErr || !designRow) {
                return callback(getVideoErr || '该模板不存在或已下架', null);
            }
            // 模板发布前已预览, 故不需要排版
            var ret = {
                designId : designRow.design_id,
                designNm : designRow.design_name,
                productId : 0,
                productNm : '',
                pageWidth : designRow.width,
                pageHeight : designRow.height,
                sceneThumbs : retUtil.safe_parser_JSON_string(designRow.thumbs) || [],
                coreStructure : retUtil.safe_parser_JSON_string(designRow.tg_data)
            };
            return callback(null, ret);
        });
    };

    /**
     * 获取用户视频作品文档内容
     *
     * @author 王俊
     * @author 2017-11-17
     *
     * @param docId     视频作品表唯一标识
     * @param userId    用户唯一标识
     * @param callback  回调
     *          error: 查询失败
     *          data: 参见接口 : http://114.55.172.253:7000/project/11/interface/api/43
     */
    documentUtil.getVideoUserDocContent = function (docId, userId, callback) {
        // 获取视频作品内容
        var entity = new YjxVideoUserDocModel();
        entity.getProductInfo(docId, userId, function(getProductErr, productRow){
            if(getProductErr || !productRow) {
                return callback(getProductErr || '当前作品不存在或者已删除', null);
            }
            if(Number(productRow.design_publish) === 0) {
                return callback('作品模板异常，暂无法修改', null);
            }
            var ret = {
                designId : productRow.design_id,
                designNm : productRow.design_name,
                productId : productRow.doc_id,
                productNm : productRow.doc_name,
                pageWidth : productRow.width,
                pageHeight : productRow.height,
                sceneThumbs : retUtil.safe_parser_JSON_string(productRow.sceneThumbs),
                coreStructure : retUtil.safe_parser_JSON_string(productRow.tg_data)
            };
            return callback(null, ret);
        });
    };


    /**
     * 以用户作品为模板, 返回对应的数据
     *
     * @author 王俊
     * @date 2017-11-18
     *
     * @param docId     用户作品唯一标识
     * @param userId    用户唯一标识
     * @param callback  回调
     *          err: 错误原因
     *          data {
     *              tmplId: 模板 id,
     *              opType: 前端业务分类, 暂定如下: 1 竖屏(单页/印品等)  2 视频  3 PPT,
     *              docString: 参见接口: http://114.55.172.253:7000/project/11/interface/api/100
     *          }
     */
    documentUtil.getUserDocCopyTmpl_v1_0 = function(docId, userId, callback){

        var totalTasks = [];
        // 1. 获取作品信息, 并移除作品相关 id
        totalTasks.push(function (callback) {
            documentUtil.getUserDocContent_v1_0(docId, userId, function (error, data) {
                if (error || !data || !data.docString) {
                    return callback(error || '该作品不存在或已删除', null);
                }
                data.docId = 0; // 移除作品标记
                data.opType = Number(data.opType);
                // 重组设计数据
                if(data.opType === 1) {
                    data.docString.productId = 0;
                    data.docString.productNm = '';
                }
                // 重组 视频 数据
                else if (data.opType === 2) {
                    data.docString.productId = 0;
                    data.docString.productNm = '';
                }
                // 重组ppt数据
                else if (data.opType === 3) {
                    data.docString.doc_id = 0;
                    data.docString.doc_name = '';
                } else {
                    return callback('该作品不存在或已删除', null);
                }
                return callback(error, data)
            });
        });
        // 2. 获取作品的统一模板 id
        totalTasks.push(function (data, callback) {
            // ppt 暂不支持处理
            if(data.opType === 3) {
                return callback('暂不支持 ppt', data);
            }
            var entity = new YjxUniUserDocModel();
            // 设计
            if(data.opType === 1) {
                entity.getDesignUserDocUniItemId(docId, function (error, tmplInfo) {
                    if(error) {
                        return callback(error, data);
                    }
                    if(!tmplInfo || !tmplInfo.uni_item_id) {
                        return callback('作品模板异常，暂无法修改', data);
                    }
                    data.tmplId = tmplInfo.uni_item_id;
                    return callback(error, data);
                });
            }
            // 视频
            else if(data.opType === 2) {
                entity.getVideoUserDocUniItemId(docId, function (error, tmplInfo) {
                    if(error) {
                        return callback(error, data);
                    }
                    if(!tmplInfo || !tmplInfo.uni_item_id) {
                        return callback('作品模板异常，暂无法修改', data);
                    }
                    data.tmplId = tmplInfo.uni_item_id;
                    return callback(error, data);
                });
            } else {
                return callback('暂不支持的分类', data);
            }
        });
        async.waterfall(totalTasks, function (error, data) {
            return callback(error, data);
        });
    };

    /**
     * 创建用户作品
     *
     * @author 王俊
     * @date 2017-11-19
     *
     * @param userId    用户唯一标识
     * @param tmplId    模板唯一标识
     * @param docString 作品核心字符串 参见接口: http://114.55.172.253:7000/project/11/interface/api/14
     * @param callback  回调
     *          error : 创建作品失败
     *          data : {
     *               "docId" : 创建的统一作品 id,
     *               "opType" : 创建的作品所属业务分类, 1 竖屏类型(单页/印品), 2 视频类型, 3 ppt 类型
     *          }
     */
    documentUtil.newUserDoc_v1_0 = function (userId, tmplId, docString, callback) {
        var opt = {
            userId : userId,
            opType : 2, // 默认为 2 (视频)
            tmplId : tmplId,
            watermark : 1,  // 模板作品均设置水印
        };
        documentUtil.newUniUserDoc(opt, function (newUniDocErr, uniDocInfo) {
            if(newUniDocErr) {
                return callback(newUniDocErr);
            }
            var item_type = Number(uniDocInfo.tmplBaseInfo.item_type);
            var ret = {
                docId : uniDocInfo.uniDocId
            };

            // 设计模板创建设计作品
            if(item_type === 10) {
                documentUtil.newDesignUserDoc(userId, uniDocInfo.uniDocId, uniDocInfo.tmplBaseInfo.item_id, docString, function (error, docInfo) {
                    if(error) {
                        return callback(error, null);
                    }
                    ret.opType = 1; // 前端业务逻辑, 1 标记设计
                    ret.productId = docInfo.productId;
                    return callback(error, ret);
                });
            }
            // 创建 ppt
            else if (item_type === 20) {
                documentUtil.newPptUserDoc(userId, uniDocInfo.uniDocId, uniDocInfo.tmplBaseInfo.item_id, docString, function (error, docInfo) {
                    if(error) {
                        return callback(error, null);
                    }
                    ret.opType = 3; // 前端业务逻辑, 3 标记ppt
                    return callback(error, ret);
                });
            }
            // 创建 视频
            else  if(item_type === 30) {
                documentUtil.newVideoUserDoc(userId, uniDocInfo.uniDocId, uniDocInfo.tmplBaseInfo.item_id, docString, function (error, docInfo) {
                    if(error) {
                        return callback(error, null);
                    }
                    ret.productId = docInfo.productId;
                    ret.opType = 2; // 前端业务逻辑, 2 标记视频
                    return callback(error, ret);
                });
            }
        });
    };
    /**
     * 创建用户作品(debug)
     *
     * @author 王俊
     * @date 2017-12-28
     *
     * @param userId    用户唯一标识
     * @param tmplId    模板唯一标识
     * @param docString 作品核心字符串 参见接口: http://114.55.172.253:7000/project/11/interface/api/14
     * @param callback  回调
     *          error : 创建作品失败
     *          data : {
     *               "docId" : 创建的统一作品 id,
     *               "opType" : 创建的作品所属业务分类, 1 竖屏类型(单页/印品), 2 视频类型, 3 ppt 类型
     *          }
     */
    documentUtil.newUserDoc_v1_0_for_debug = function (userId, tmplId, docString, callback) {
        documentUtil.newUniUserDoc_for_debug(userId, tmplId, function (newUniDocErr, uniDocId, tmplBaseInfo) {
            if(newUniDocErr) {
                return callback(newUniDocErr);
            }
            var item_type = Number(tmplBaseInfo.item_type);
            var ret = {
                docId : uniDocId
            };

            // 设计模板创建设计作品
            if(item_type === 10) {
                documentUtil.newDesignUserDoc(userId, uniDocId, tmplBaseInfo.item_id, docString, function (error, docInfo) {
                    if(error) {
                        return callback(error, null);
                    }
                    ret.opType = 1; // 前端业务逻辑, 1 标记设计
                    ret.productId = docInfo.productId;
                    return callback(error, ret);
                });
            }
            // 创建 视频
            else  if(item_type === 30) {
                documentUtil.newVideoUserDoc(userId, uniDocId, tmplBaseInfo.item_id, docString, function (error, docInfo) {
                    if(error) {
                        return callback(error, null);
                    }
                    ret.productId = docInfo.productId;
                    ret.opType = 2; // 前端业务逻辑, 2 标记视频
                    return callback(error, ret);
                });
            } else  {
                return callback('暂不支持的类型', null);
            }
        });
    };

    /**
     * 更新用户作品
     *
     * @author 王俊
     * @date 2017-11-19
     *
     * @param userId    用户唯一标识
     * @param uniDocId  作品唯一标识
     * @param docString 作品核心字符串, 参见接口: http://114.55.172.253:7000/project/11/interface/api/15
     * @param callback  回调
     *          error: 创建作品失败
     *          data: {
     *              "docId" : 创建的统一作品 id,
     *              "opType" : 创建的作品所属业务分类, 1 竖屏类型(单页/印品), 2 视频类型, 3 ppt 类型
     *          }
     */
    documentUtil.updateUserDoc_v1_0 = function (userId, uniDocId, docString, callback) {

        var docEntity = new YjxUniUserDocModel();
        docEntity.checkUniUserDocType(uniDocId, function (err, docInfo) {
            if(err) {
                return callback(err, null);
            }
            var docType = Number(docInfo.doc_type); // 作品类型
            var docId = Number(docInfo.doc_id);     // 作品子表唯一标识
            var ret = {
                docId : uniDocId
            };
            // 设计
            if(docType === 10) {
                documentUtil.updateDesignUserDoc(userId, docId, docString, function (updateErr, docInfo) {
                    if(updateErr) {
                        return callback(updateErr, null);
                    }
                    ret.opType = 1; // 前端业务逻辑, 1 标记设计
                    return callback(updateErr, ret);
                });
            }
            // ppt
            else if(docType === 20) {
                documentUtil.updatePptUserDoc(userId, docId, docString, function (updateErr, docInfo) {
                    if(updateErr) {
                        return callback(error, null);
                    }
                    ret.opType = 3; // 前端业务逻辑, 3 标记ppt
                    return callback(updateErr, ret);
                });
            }
            // 视频
            else  if(docType === 30) {
                documentUtil.updateVideoUserDoc(userId, docId, docString, function (updateErr, docInfo) {
                    if(updateErr) {
                        return callback(updateErr, null);
                    }
                    ret.opType = 2; // 前端业务逻辑, 2 标记视频
                    return callback(updateErr, ret);
                });
            }
        });
    };
    /**
     * 创建统一作品
     *
     * @author 王俊
     * @date 2017-11-19
     *
     * @param {Object} options
     * @param {Number} options.userId
     * @param {Number} options.opType 1 设计(废弃), 2 视频, 3 ppt(废弃), 4, 自由创建作品
     * @param {Number} [options.tmplId] options.opType 为 2 时, 指定模板 id
     * @param {Number} [options.watermark] 作品是否携带水印, 默认为 0
     * @param {Function} callback  回调
     *          err: 创建统一作品失败
     *          {
     *              uniDocId: 统一作品标识
     *              tmplBaseInfo: {
     *                    uni_item_id     : 统一模板标识
     *                    item_type       : 统一模板类型, 10 设计模板 20 ppt 模板 30 视频模板
     *                    item_id         : 模板子表 id(设计模板子表, ppt 模板子表, 视频模板子表)
     *                    tmpl_set_id     : 该模板所属模板组 id
     *                    tmpl_set_title  : 该模板所属模板组标题
     *                    show_type_id    : 该模板所属显示分类 id
     *                    show_type_title : 该模板所属显示分类标题
     *              }
     *          }
     *
     */
    documentUtil.newUniUserDoc = function (options, callback) {
        var tasks = [];
        // 1. 查验用户
        tasks.push(function (callback) {
            var entity = new YjxUserModel({
                user_id : options.userId,
                del_flg : 0
            });
            entity.findFromDB(function (error, users) {
                if(error || !users || users.length <= 0) {
                    return callback(error || '该用户不存在');
                }
                var data = {};
                data.userInfo = users[0];
                return callback(error, data);
            }, 0,1);
        });
        // 2. 查验模板
        tasks.push(function (data, asyCallback) {
            if(options.opType === 4) {
                data.tmplBaseInfo = {
                    show_type_id : 2,   // 显示分类, 写死为 2
                    form_id : 0,        // 自由创建, 暂不支持表单
                };
                return asyCallback(null, data)
            }
            var uniEntity = new YjxUniItemsModel();
            uniEntity.getUniTmplShowTyeInfo(options.tmplId, function (error, tmplBaseInfo) {
                data.tmplBaseInfo = tmplBaseInfo;
                return asyCallback(error, data);
            });
        });
        // 3. 创建统一用户作品
        tasks.push(function (data, asyCallback) {
            var uniDoc = new YjxUniUserDocModel({
                user_id: options.userId,
                watermark : options.watermark || 0,
                show_type_id : data.tmplBaseInfo.show_type_id,
                form_id : data.tmplBaseInfo.form_id,    // 作品携带表单 id
                form_flg : 0,                           // 表单收集功能默认 0:不使用表单
                update_by : options.userId
            });
            uniDoc.saveToDB(function (saveErr, uniDocId) {
                data.uniDocId = uniDocId;
                return asyCallback(saveErr, data);
            })
        });
        // 顺序执行
        async.waterfall(tasks, function (newUniDocErr, data) {
            if(newUniDocErr) {
                return callback(newUniDocErr, null);
            }
            var retData = {
                uniDocId: data.uniDocId, tmplBaseInfo: data.tmplBaseInfo
            };
            return callback(newUniDocErr, retData);
        });
    };

    /**
     * 创建统一作品(debug)
     *
     * @author 王俊
     * @date 2017-12-28
     *
     * @param userId    用户唯一标识(此函数会检查用户 id 有效性)
     * @param tmplId    作品对应的统一模板标识(取 show_type_id 使用)
     * @param callback  回调
     *          err: 创建统一作品失败
     *          uniDocId: 统一作品标识
     *          tmplBaseInfo: {
     *              uni_item_id     : 统一模板标识
     *              item_type       : 统一模板类型, 10 设计模板 20 ppt 模板 30 视频模板
     *              item_id         : 模板子表 id(设计模板子表, ppt 模板子表, 视频模板子表)
     *              tmpl_set_id     : 该模板所属模板组 id
     *              tmpl_set_title  : 该模板所属模板组标题
     *              show_type_id    : 该模板所属显示分类 id
     *              show_type_title : 该模板所属显示分类标题
     *          }
     */
    documentUtil.newUniUserDoc_for_debug = function (userId, tmplId, callback) {
        var tasks = [];
        // 2. 查验模板
        tasks.push(function (asyCallback) {
            var uniEntity = new YjxUniItemsModel({
                uni_item_id : tmplId,
                del_flg : 0
            });
            var data = {};
            uniEntity.findFromDB(function (error, items) {
                if(!items || items.length <=0) {
                    return callback(error || '模板不存在', null)
                }
                data.tmplBaseInfo = items[0];
                return asyCallback(error, data);
            })
        });
        // 3. 创建统一用户作品
        tasks.push(function (data, asyCallback) {
            var uniDoc = new YjxUniUserDocModel({
                user_id: userId,
                show_type_id : 0,
                form_id : 0,    // 作品携带表单 id
                form_flg : 0,                           // 表单收集功能默认 0:不使用表单
                update_by : userId
            });
            uniDoc.saveToDB(function (saveErr, uniDocId) {
                data.uniDocId = uniDocId;
                return asyCallback(saveErr, data);
            })
        });
        // 顺序执行
        async.waterfall(tasks, function (newUniDocErr, data) {
            if(newUniDocErr) {
                return callback(newUniDocErr, null);
            }
            return callback(newUniDocErr, data.uniDocId, data.tmplBaseInfo);
        });
    };

    /**
     * 创建用户设计作品
     *
     * @author 王俊
     * @date 2017-11-19
     *
     * @param userId       用户唯一标识
     * @param uniDocId     统一作品 id
     * @param designId     设计 id(设计模板表 id)
     * @param docString    设计作品核心结构
     * @param callback     回调
     *              err 创建作品失败
     *              data: {
     *                  designId: 作品对应的模板(设计模板)id
     *                  productId: 作品 id(设计作品)
     *              }
     * todo 复制自 tg3Util.saveTgAndFineTuneInfo_v5_3 待测
     */
    documentUtil.newDesignUserDoc = function (userId, uniDocId, designId, docString, callback) {
        // 解析 docString
        var doc = retUtil.safe_parser_JSON_string(docString);
        if(!doc) {
            return callback('参数错误', null);
        }
        async.parallel({
            getDesign: function(callback){
                // 检索design
                var entityD = new TgDesignDocModel({
                    design_id: doc.designId,
                    del_flg: 0
                });
                entityD.findFromDB(function(err, items) {
                    if (err || !items || items.length <= 0) {
                        console.log('yjx/v1/util/documentUtil.js [newDesignUserDoc] Check design_id Err: ' + err);
                        return callback(err || '该模板不存在或已下架', null);
                    }
                    return callback(null, items[0]);
                });
            },
            getUser: function(callback){
                var entity = new YjxUserModel({
                    user_id : userId,
                    del_flg : 0
                });
                entity.findFromDB(function(err, items){
                    if (err || !items || items.length <= 0){
                        console.log('yjx/v1/util/documentUtil.js [newDesignUserDoc] Check user_id Err: ' + err);
                        return callback(err, null);
                    }
                    return callback(err, items[0]);
                });
            }

        }, function(error, result){
            if (error) {
                return callback(error, null);
            }
            var userItem = result.getUser;
            var designItem = result.getDesign;
            // 新规
            var newDocEntity = new YjxDesignUserDocModel({
                tg_id: designItem.tg_id,
                map_id: designItem.map_id,
                uni_doc_id :uniDocId,
                design_id: designItem.design_id,
                doc_name: doc.productNm || '我的作品',// doc.coreStructure.name
                user_id: userItem.user_id,
                user_type: userItem.user_type,
                purpose: 0,
                size_id: designItem.size_id,
                type_id: designItem.type_id,
                video_size_id: designItem.video_size_id,
                video_pos : designItem.video_pos,
                data: JSON.stringify(doc.coreStructure) || '',
                hash_tag: JSON.stringify(doc.tag) || '[]',// TODO
                finetune_data:doc.textObjects,
                finetune_flg:1,
                ver: doc.coreStructure.version || 0,
                update_by: userItem.user_id
            });
            // insert document
            newDocEntity.saveToDB(function(err, newDocId){
                if (err) {
                    console.log('yjx/v1/util/documentUtil.js [newDesignUserDoc] Ins Doc Err: '+err);
                    return callback(err,null);
                }
                var retData = {
                    designId: designItem.design_id,
                    productId: newDocId
                };
                return callback(null, retData);
            });
        });
    };
    /**
     * 更新用户设计作品
     *
     * @author 王俊
     * @date 2017-11-19
     *
     * @param userId       用户唯一标识
     * @param docId        设计作品 id(设计作品子表 id)
     * @param docString    设计作品核心结构
     * @param callback     回调
     *              err 更新设计作品失败
     *              data : {
     *                      designId: 设计作品对应的模板 id(设计模板子表)
     *                      productId: 设计作品 id(设计作品子表)
     *              }
     */
    documentUtil.updateDesignUserDoc = function (userId, docId, docString, callback) {
        var doc = retUtil.safe_parser_JSON_string(docString);
        if(!doc) {
            return callback('参数错误', null);
        }
        async.parallel({
            getDesign: function(callback){
                // 检索design
                var entityD = new TgDesignDocModel({
                    design_id: doc.designId,
                    del_flg: 0
                });
                entityD.findFromDB(function(err, items) {
                    if (err || !items || items.length <= 0) {
                        console.log('yjx/v1/util/documentUtil.js [newDesignUserDoc] Check design_id Err: ' + err);
                        return callback(err || '该模板不存在或已下架', null);
                    }
                    return callback(null, items[0]);
                });
            },
            getUser: function(callback){
                var entity = new YjxUserModel({
                    user_id : userId,
                    del_flg : 0
                });
                entity.findFromDB(function(err, items){
                    if (err || !items || items.length <= 0){
                        console.log('yjx/v1/util/documentUtil.js [newDesignUserDoc] Check user_id Err: ' + err);
                        return callback(err, null);
                    }
                    return callback(err, items[0]);
                });
            }
        }, function(error, result){
            if (error) {
                return callback(error, null);
            }
            var userItem = result.getUser;
            var designItem = result.getDesign;
            // 更新doc
            var updDocEnt = new YjxDesignUserDocModel({
                doc_id: doc.productId,// Key
                doc_name: doc.productNm || '我的作品',// doc.coreStructure.name
                data: JSON.stringify(doc.coreStructure) || '',
                hash_tag: JSON.stringify(doc.tag) || '[]',// TODO
                finetune_data:doc.textObjects,
                finetune_flg:1,
                ver: doc.coreStructure.version || 0,
                update_by: userItem.user_id
            });
            updDocEnt.updateToDB(function(err){
                if (err) {
                    console.log('yjx/v1/util/documentUtil.js [newDesignUserDoc] Upd Doc Err: '+err);
                    return callback(err, null)
                }
                // 逻辑删除page
                var delPgEnt = new YjxDesignUserPageModel({
                    doc_id: doc.productId,
                    update_by: userItem.user_id
                });
                delPgEnt.delPageLogic(function(delErr){
                    if (delErr) {
                        console.log('yjx/v1/util/documentUtil.js [newDesignUserDoc] Del Pages Err: ' + delErr);
                        return callback(delErr,null);
                    }
                    // 逻辑删除pc
                    var delPcEnt = new YjxDesignUserPcModel({
                        doc_id: doc.productId,
                        update_by: userItem.user_id
                    });
                    delPcEnt.delPcLogic(function(delErr2){
                        if (delErr2) {
                            console.log('tg.js [saveUserDocOnly(upd)] Del PCs Err: ' + delErr2);
                            return callback(delErr2,null);
                        }
                        // 返回值
                        var retData = {
                            designId: designItem.design_id,
                            productId: doc.productId
                        };
                        return callback(delErr2, retData);
                    });
                });
            });
        });
    };


    /**
     * 删除用户设计作品
     *
     * @author 李强
     * @date 2017-11-20
     *
     * @param userId       用户唯一标识
     * @param docId     设计作品 id(设计作品子表 id)
     * @param callback     回调
     *              err 更新设计作品失败
     *              data : {}
     */
    documentUtil.deleteDesignUserDoc = function (userId, docId, callback) {
        //通过用户设计作品id,找到对用用户的设计模版id
        // 逻辑删除
        var delUdmEnt = new YjxDesignUserDocModel({
            doc_id: docId,
            user_id: userId,
            del_flg:1
        });
        delUdmEnt.updateToDB(function(err) {
            return callback(err, {});
        })
    };

    /**
     * 创建用户 ppt 作品
     *
     * @deprecated 一键秀暂不支持 PPT
     *
     * @author 王俊
     * @date 2017-11-19
     *
     * @param userId    用户唯一标识
     * @param uniDocId  对应的统一作品 id
     * @param tmplId    ppt 模板 id(PPT模板表 id)
     * @param docString ppt 作品核心结构
     * @param callback  回调
     *          err: 创建 ppt 作品失败
     *          data: {
     *               user_id: 用户唯一标识,
     *               doc_id: ppt 作品唯一标识(ppt 作品表),
     *               doc_name: ppt 作品名称,
     *               pages: ppt 页页码数组, 按 pageIndex 排序
     *          }
     */
    documentUtil.newPptUserDoc = function (userId, uniDocId, tmplId, docString, callback) {
        var doc = retUtil.safe_parser_JSON_string(docString);
        if(!doc) {
            return callback('参数错误', null);
        }
        // 检查用户和模板
        async.parallel({
            getDoc: function(callback){
                var entityDoc = new ItbTemplateModel({
                    tmpl_id:doc.tmpl_id,
                    del_flg:0
                });
                entityDoc.findFromDB(function(err, items) {
                    if (err || !items || items.length <=0) {
                        console.log('yjx/v1/util/documentUtil.js [newPptUserDoc] check doc_id error: ' + err);
                        return callback(err || '该模板不存在或已下架', null);
                    }
                    return callback(null, items[0]);
                });
            },
            getUserId: function(callback){
                // 检索user
                var entity = new YjxUserModel({
                    user_id : userId,
                    del_flg : 0
                });
                entity.findFromDB(function(error, items){
                    if (error){
                        console.log('yjx/v1/util/documentUtil.js [newPptUserDoc] check user error: ' + err);
                        return callback(error || '该用户不存在', null);
                    }
                    return callback(null, items[0].user_id);
                });
            }

        }, function(error, result){
            if (error) {
                return callback(error, null);
            }
            var userId = result.getUserId;
            var docItem = result.getDoc;
            // 新规
            var newDocEntity = new YjxPptUserDocModel({
                base_doc_id: docItem.tmpl_id,
                uni_doc_id : uniDocId,
                doc_name: doc.doc_name||'我的作品',
                user_id: userId,
                user_type: 1,
                publish: 0,
                ver:docItem.ver,
                update_by: userId
            });
            // insert document
            newDocEntity.saveToDB(function(err, newDocId){
                if (err) {
                    console.log('yjx/v1/util/documentUtil.js [newPptUserDoc] insert doc error: '+err);
                    return callback(err, null);
                }

                // 新建pages
                var pageEntity = new YjxPptUserPageModel({
                    doc_id: newDocId,
                    update_by: userId// TODO
                });
                pageEntity.updatePages(function(err3,result){
                    if (err3) {
                        console.log('yjx/v1/util/documentUtil.js [newPptUserDoc] insert pages error: '+err3);
                        return callback(err3, null);
                    }

                    var pageIds = result || [];// 已按page_index排序
                    var retData = {
                        user_id: userId,
                        doc_id: newDocId,
                        doc_name: doc.doc_name||'我的作品',
                        pages: pageIds
                    };
                    return callback(err3, retData);
                },newDocId,1,userId,doc.pages);
            });
        });
    };
    /**
     * 更新用户 ppt 作品
     *
     * @deprecated 一键秀暂不支持 PPT
     *
     * @author 王俊
     * @date 2017-11-19
     *
     * @param userId    用户唯一标识
     * @param docId    ppt 作品id (ppt 作品子表唯一标识)
     * @param docString ppt 作品核心结构
     * @param callback  回调
     *          err: 更新 ppt 作品失败
     *          data: {
     *               user_id: 用户唯一标识,
     *               doc_id: ppt 作品唯一标识(ppt 作品表),
     *               doc_name: ppt 作品名称,
     *               pages: ppt 页页码数组, 按 pageIndex 排序
     *          }
     */
    documentUtil.updatePptUserDoc = function (userId, docId, docString, callback) {
        // proc
        var doc = retUtil.safe_parser_JSON_string(docString);
        if(!doc) {
            return callback('参数错误', null);
        }
        async.parallel({
            getDoc: function(callback){
                var entityDoc = new YjxPptUserDocModel({
                    doc_id:doc.doc_id,
                    del_flg:0
                });
                entityDoc.findFromDB(function(err, items) {
                    if (err || !items || items.length <= 0) {
                        console.log('yjx/v1/util/documentUtil.js [updatePptUserDoc] check doc_id error: ' + err);
                        return callback(err || '该作品不存在或已删除', null);
                    }
                    return callback(null, items[0]);
                });
            },
            getUserId: function(callback){
                // 检索user
                var entity = new YjxUserModel({
                    user_id : userId,
                    del_flg : 0
                });
                entity.findFromDB(function(error, items){
                    if (error || ! items || items.length <= 0){
                        console.log('yjx/v1/util/documentUtil.js [updatePptUserDoc] select user error: '+error);
                        return callback(error || '该用户不存在', null);
                    }
                    return callback(null, items[0].user_id);
                });
            }
        }, function(error, result){
            if (error) {
                return callback(error, null);
            }
            var userId = result.getUserId;
            var docItem = result.getDoc;
            // 更新
            var updDocEntity = new YjxPptUserDocModel({
                doc_id: docItem.doc_id,// Key
                doc_name: doc.doc_name||'我的作品', // 更新name
                user_id: userId,
                update_by: userId
            });
            updDocEntity.updateToDB(function(err){
                if (err) {
                    console.log('yjx/v1/util/documentUtil.js [updatePptUserDoc] update doc error: '+err);
                    return callback(err, null);
                }
                // 删除pages
                var pageEntity = new YjxPptUserPageModel({
                    doc_id: docItem.doc_id,
                    update_by: userId
                });
                pageEntity.deletePagesByDocIdLogic(function(err2){
                    if (err2) {
                        console.log('yjx/v1/util/documentUtil.js [updatePptUserDoc]delete pages error: '+err2);
                        return callback(err2, null);
                    }
                    // 新建/更新pages
                    pageEntity.updatePages(function(err3,result){
                        if (err3) {
                            console.log('yjx/v1/util/documentUtil.js [updatePptUserDoc] insert pages error: '+err3);
                            return callback(err3, null);
                        }
                        var pageIds = result || [];// 已按page_index排序
                        var retData = {
                            user_id: userId,
                            doc_id: docItem.doc_id,
                            doc_name: doc.doc_name||'我的作品',
                            pages: pageIds
                        };
                        return callback(err3, retData);
                    },docItem.doc_id,1,userId,doc.pages);
                });
            });

        });
    };
    /**
     * 创建用户视频作品
     *
     * @author 王俊
     * @date 2017-11-19
     *
     * @param userId    用户唯一标识
     * @param uniDocId  统一作品唯一标识
     * @param designId  模板 id(视频设计子表id)
     * @param docString 视频作品核心结构
     * @param callback  回调
     *            err: 创建视频作品失败
     *            data: {
     *               productId : 新创建视频作品唯一标识(视频作品表),
     *               designId : 视频作品对应的模板唯一标识(视频模板表)
     *            }
     */
    documentUtil.newVideoUserDoc = function (userId, uniDocId, designId, docString, callback) {
        var videoTg = retUtil.safe_parser_JSON_string(docString);
        if(!videoTg) {
            return callback('参数错误')
        }
        var userDoc = new YjxVideoUserDocModel();
        userDoc.uni_doc_id = uniDocId;
        userDoc.doc_name = videoTg.productNm || '我的作品';
        userDoc.design_id = videoTg.designId;
        userDoc.tg_data = JSON.stringify(videoTg.coreStructure);
        // todo 待确认表是否添加 ver 字段
        // userDoc.ver = videoTg.coreStructure.version;
        userDoc.user_id = userId;
        userDoc.update_by = userId;
        userDoc.purpose = 0; // 标记普通文档
        // 查询模板信息
        var designEntity = new VideoDesignDocModel({
            design_id : videoTg.designId,
            del_flg : 0
        });
        designEntity.findFromDB(function(getDesignErr, designs){
            if(getDesignErr || !designs || designs.length <= 0) {
                return callback(getDesignErr || '该模板不存在或已下架', null);
            }
            // 提取模板相关信息
            var design = designs[0];
            userDoc.size_id = design.size_id;
            userDoc.type_id = design.type_id;
            userDoc.thumbs = design.thumbs;
            userDoc.saveToDB(function(insertErr, insertId){
                if(insertErr) {
                    return callback(insertErr, null);
                }
                var ret = {
                    productId : insertId,
                    designid : videoTg.design_id
                };
                return callback(null, ret)
            });
        });
    };
    /**
     * 修改用户视频作品
     *
     * @author 王俊
     * @date 2017-11-19
     *
     * @param userId    用户唯一标识
     * @param docId     视频作品 id(视频设计子表id)
     * @param docString 视频作品核心结构
     * @param callback  回调
     *            err: 修改视频作品失败
     *            data: {
     *               productId : 新创建视频作品唯一标识(视频作品表),
     *               designId : 视频作品对应的模板唯一标识(视频模板表)
     *            }
     */
    documentUtil.updateVideoUserDoc = function (userId, docId, docString, callback) {
        var videoTg = retUtil.safe_parser_JSON_string(docString);
        if(!videoTg) {
            return callback('参数错误', null);
        }
        // 1. 查询作品当前修改次数
        var entity = new YjxVideoUserDocModel({
            doc_id: docId,
            user_id : userId,
            del_flg : 0
        });
        entity.findFromDB(function(findVideoDocErr, videos) {
            if(findVideoDocErr || !videos || videos.length <=0) {
                return callback(findVideoDocErr || '作品不存在或已删除', null);
            }
            var oldDoc = videos[0];

            // 注意: 若旧文档生成中, 不予修改, 返回报错
            if (Number(oldDoc.state) === 1) {
                return callback('当前作品生成中, 请稍后保存', null);
            }

            var userDoc = new YjxVideoUserDocModel();
            userDoc.user_id = userId;
            userDoc.doc_name = videoTg.productNm || '我的作品';
            userDoc.design_id = videoTg.designId;
            userDoc.tg_data = JSON.stringify(videoTg.coreStructure);
            // todo 待确认表是否添加 ver 字段
            // userDoc.ver = videoTg.coreStructure.version;
            userDoc.update_by = userId;
            // 清空相关信息
            userDoc.modify_cnt = Number(oldDoc.modify_cnt) + 1;
            userDoc.res_low = 0;
            userDoc.comb_res_low = 0; // updateToDB 值不能为 null
            userDoc.res_mid = 0;
            userDoc.comb_res_mid = 0;
            userDoc.res_high = 0;
            userDoc.comb_res_high = 0;
            userDoc.dirty = 1;

            // 注意, 还需要修改作品状态标记
            userDoc.state = 0;  // 作品修改后标记作品待生成状态

            // 2. 修改
            userDoc.doc_id = videoTg.productId;
            userDoc.updateToDB(function(updateErr){
                //todo 逻辑删除相关视频资源
                var ret = {
                    productId:videoTg.productId,
                    designId : videoTg.designId
                };
                // 同时清空 redis 状态
                if(!updateErr) {
                    VideoRenderLuadUtil.lua_video_delete_render(userDoc.doc_id, function (error) {
                        if(error) {
                            console.log('VideoRenderLuadUtil.lua_video_delete_render: ' + error);
                        }
                    });
                }
                return callback(updateErr, ret)
            });
        });
    };

    /**
     * 获取用户作品预览(未排版则先排版)
     *
     * @author 王俊
     * @date 2017-11-19
     *
     * @param userId    用户唯一标识
     * @param uniDocId  用户统一作品唯一标识
     * @param callback  回调
     *          err: 排版失败
     *          data: 参见接口: http://114.55.172.253:7000/project/11/interface/api/46
     */
    documentUtil.getDocPreview_v1_0 = function (userId, uniDocId, callback) {
        var totalTasks = [];
        // 1. 获取作品基础分类信息
        totalTasks.push(function (callback) {
            var uniDoc = new YjxUniUserDocModel();
            uniDoc.checkUniUserDocType(uniDocId, function (checkErr, typeInfo) {
                if(checkErr) {
                    return callback(checkErr, null);
                }
                var data = {};
                data.docType = Number(typeInfo.doc_type);
                data.docId = Number(typeInfo.doc_id);
                data.video_bg_id = Number(typeInfo.video_bg_id);
                data.form_flg = Number(typeInfo.form_flg);
                data.ret = {
                    id : typeInfo.uni_doc_id,
                    watermark : typeInfo.watermark,
                    watermarkPay : typeInfo.wm_paid,
                    createDay : typeInfo.createDay
                };
                // '0:不使用表单, 1:使用表单(开启), 2:使用表单(关闭)',
                data.ret.formState = data.form_flg === 1 ? 1 : 0;  // 表单状态, 1:使用表单(开启), 2:使用表单(关闭)
                data.ret.showFormFb = data.form_flg === 0 ? 0 : 1; // 是否显示表单反馈, 0 不显示, 1 显示, 开启过就显示

                data.typeInfo = typeInfo;
                // 作品当前无水印, 且已支付, 预览才不带水印, 否则都带水印
                data.withWm = (!data.ret.watermark && data.ret.watermarkPay) ? 0 : 1;
                return callback(checkErr, data)
            });
        });
        // 2. 分别获取预览
        totalTasks.push(function (data, callback) {
            // 设计作品
            if(data.docType === 10) {
                documentUtil.getUserDesignDocPreview(userId, data.docId, data.withWm, function (previewErr, result) {
                    if(previewErr) {
                        return callback(previewErr, null);
                    }
                    data.ret.image = result.image;
                    data.ret.docNm = result.docNm;
                    data.ret.opType = 1; // 前端业务逻辑, 1 标记设计
                    return callback(previewErr, data);
                })
            }
            // ppt 作品 暂不支持 ppt
            // else if(data.docType === 20) {
            //     documentUtil.getUserPPTDocPreview(userId, docId, function (previewErr, data) {
            //         if(previewErr) {
            //             return callback(previewErr, null);
            //         }
            //         data.ret.image = data.image;
            //         data.ret.docNm = data.docNm;
            //         data.ret.opType = 3; // 前端业务逻辑, 3 标记 ppt
            //         return callback(previewErr, data);
            //     });
            // }
            // 视频作品
            else if(data.docType === 30) {
                documentUtil.getUserVideoDocPreview(userId, data.docId, data.video_bg_id, data.withWm, function (previewErr, result) {
                    if(previewErr) {
                        return callback(previewErr, null);
                    }
                    data.ret.video = result.video;
                    data.ret.docNm = result.docNm;
                    data.ret.bgInfo = {
                        currentBg : result.bgInfo,
                        column : 3                  // 固定当前列数
                    };
                    data.ret.opType = 2; // 前端业务逻辑, 2 标记视频
                    return callback(previewErr, data);
                });
            } else {
                return callback('暂不支持的分类', data);
            }
        });
        // 3. 如果是设计作品, 则判断是否支持高清下载
        totalTasks.push(function (data, callback) {
            if(data.docType !== 10) {
                return callback(null, data);
            }
            documentUtil.ckeckUserDesignDocSupportHQ(data.docId, function (checkErr, supportHQ) {
                if(checkErr) {
                    return callback(checkErr, null);
                }
                data.ret.supportHQ = supportHQ;
                return callback(checkErr, data);
            });
        });
        // 4. 如果是视频, 获取背景列表
        totalTasks.push(function (data, callback) {
            if(data.docType !== 30) {
                return callback(null, data);
            }
            // 获取视频可用背景
            documentUtil.getVideoUserDocBgList_v1_0(userId, uniDocId, 0, 3, 0,function (getBgListErr, bgData) {
                // 取不到背景信息也可ren
                // if(getBgListErr) {
                //     return callback(getBgListErr);
                // }
                if(bgData) {
                    data.ret.bgInfo.list = bgData.list || [];
                }
                return callback(null, data);
            });
        });
        // 5. 获取作品对应的模板子表 id
        totalTasks.push(function (data, callback) {
            var entity = null;
            if(data.docType === 10){
                entity = new YjxDesignUserDocModel({doc_id:data.docId, del_flg:0});
            }else if(data.docType === 30){
                entity = new YjxVideoUserDocModel({doc_id: data.docId, del_flg: 0});
            } else {
                return callback('暂不支持的分类', data);
            }
            entity.findFromDB(function (err, items) {
                if(err || !items || items.length <0){
                    return callback(err || '作品不存在或已删除', data);
                }
                data.designId = items[0].design_id;
                return callback(null,data);
            });
        });
        // 6. 根据模板子表 id, 查询视频价格
        totalTasks.push(function (data, callback) {
            if(data.docType !== 30) return callback(null, data);
            var entity = new YjxPriceModel();
            var price_type = 2;
            entity.getPayInfoFromVideo(data.designId, price_type, function (error, prices) {
                if(CONFIG.DEBUG) {
                    data.ret.watermarkFee = 1000;
                } else  {
                    if(error || !prices || prices.length <=0) {
                        return callback(error || '查询价格失败', data);
                    }
                    data.ret.watermarkFee = prices[0].unit_price;
                }
                return callback(error, data);
            });
        });
        // 7. 根据模板子表 id, 查询设计价格
        totalTasks.push(function (data, callback) {
            if(data.docType !== 10) return callback(null, data);
            var entity = new YjxPriceModel();
            var price_type = 2;
            entity.getPayInfoFromDesign(data.designId, price_type, function (error, prices) {
                if(CONFIG.DEBUG) {
                    data.ret.watermarkFee = 1000;
                } else  {
                    if(error || !prices || prices.length <=0) {
                        return callback(error || '查询价格失败', data);
                    }
                    data.ret.watermarkFee = prices[0].unit_price;
                }
                return callback(error, data);
            });
        });

        async.waterfall(totalTasks, function (error, data) {
            if(error) {
                return callback(error, null);
            }
            return callback(error, data.ret);
        });
    };




    /**
     * 获取用户作品预览(debug未排版则先排版)
     *
     * @author 李强
     * @date 2017-12-28
     *
     * @param userId    用户唯一标识
     * @param docId  用户统一作品唯一标识
     * @param callback  回调
     *          err: 排版失败
     *
     */
    documentUtil.getDocPreview_for_debug = function (userId, docId, callback) {
        var totalTasks = [];
        // 1. 获取作品基础分类信息
        totalTasks.push(function (callback) {
            var uniDoc = new YjxUniUserDocModel();
            uniDoc.checkUniUserDocType(docId, function (checkErr, typeInfo) {
                if(checkErr) {
                    return callback(checkErr, null);
                }
                var data = {};
                data.docType = Number(typeInfo.doc_type);
                data.docId = Number(typeInfo.doc_id);
                data.video_bg_id = Number(typeInfo.video_bg_id);
                data.form_flg = Number(typeInfo.form_flg);
                data.ret = {
                    id : typeInfo.uni_doc_id,
                    watermark : typeInfo.watermark,
                    watermarkPay : typeInfo.wm_paid
                };
                // '0:不使用表单, 1:使用表单(开启), 2:使用表单(关闭)',
                data.ret.formState = data.form_flg === 1 ? 1 : 0;  // 表单状态, 1:使用表单(开启), 2:使用表单(关闭)
                data.ret.showFormFb = data.form_flg === 0 ? 0 : 1; // 是否显示表单反馈, 0 不显示, 1 显示, 开启过就显示

                data.typeInfo = typeInfo;
                // 作品当前无水印, 且已支付, 预览才不带水印, 否则都带水印
                data.withWm = (!data.ret.watermark && data.ret.watermarkPay) ? 0 : 1;
                return callback(checkErr, data)
            });
        });
        // 2. 分别获取预览
        totalTasks.push(function (data, callback) {
            // 设计作品
            if(data.docType === 10) {
                documentUtil.getUserDesignDocPreview(userId, data.docId, data.withWm, function (previewErr, result) {
                    if(previewErr) {
                        return callback(previewErr, null);
                    }
                    data.ret.image = result.image;
                    data.ret.docNm = result.docNm;
                    data.ret.opType = 1; // 前端业务逻辑, 1 标记设计
                    return callback(previewErr, data);
                })
            }
            // 视频作品
            else if(data.docType === 30) {
                documentUtil.getUserVideoDocPreview(userId, data.docId, data.video_bg_id, data.withWm, function (previewErr, result) {
                    if(previewErr) {
                        return callback(previewErr, null);
                    }
                    data.ret.video = result.video;
                    data.ret.docNm = result.docNm;
                    data.ret.opType = 2; // 前端业务逻辑, 2 标记视频
                    return callback(previewErr, data);
                });
            } else {
                return callback('暂不支持的分类', data);
            }
        });
        // 3. 获取作品对应的模板子表 id
        totalTasks.push(function (data, callback) {
            var entity = null;
            if(data.docType === 10){
                entity = new YjxDesignUserDocModel({doc_id:data.docId, del_flg:0});
            }else if(data.docType === 30){
                entity = new YjxVideoUserDocModel({doc_id: data.docId, del_flg: 0});
            } else {
                return callback('暂不支持的分类', data);
            }
            entity.findFromDB(function (err, items) {
                if(err || !items || items.length <0){
                    return callback(err || '作品不存在或已删除', data);
                }
                data.designId = items[0].design_id;
                return callback(null,data);
            });
        });

        async.waterfall(totalTasks, function (error, data) {
            if(error) {
                return callback(error, null);
            }
            return callback(error, data.ret);
        });
    };





    /**
     * 获取用户设计作品预览信息(若未排版则先排版)
     *
     * @author 王俊
     * @date 2017-11-19
     *
     * @param userId    用户唯一标识
     * @param docId     用户设计作品唯一标识(设计作品子表 id)
     * @param withWm    是否携带水印
     * @param callback  回调
     *          error: 获取预览失败
     *          data : {
     *              image: {
     *                  "thumbs":[
     *                       "http://itbour-generate.oss-cn-hangzhou.aliyuncs.com/image/U30330/2016/11/06/091954617_IqjCfwBAzWz7I683nMRf/0.jpg"
     *                     ],
     *                   "w" : 720,
     *                   "h" : 1280,
     *               }
     *               "docNm":"欢度国庆",         // 作品名称
     *          }
     * 注意: 视频背景也属于设计的一种, 故可以使用此方法进行预览/排版
     */
    documentUtil.getUserDesignDocPreview = function (userId, docId, withWm, callback) {
        // 获取文档
        var docEntity = new YjxDesignUserDocModel({
            doc_id: docId,
            del_flg: 0,
            withoutPgInfo: 1// 新文档没有pg
        });
        docEntity.getDocInfoById(function (findErr, docs) {
            if (findErr || !docs || docs.length <= 0) {
                console.log('yjx/v1/util/documentUtil.js [getUserDesignDocPreview] find doc Err: ' + findErr);
                return callback(findErr || '该作品不存在或已删除', null);
            }
            var itemInfo = docs[0];
            // 获取preview
            var pgEntity  = new YjxDesignUserPageModel({
                doc_id: docId,
                del_flg:0
            });
            pgEntity.getPageInfoById(function(error, items){
                if(error){
                    console.log('yjx/v1/util/documentUtil.js [getUserDesignDocPreview] getPageInfoById Err: '+error);
                    return callback(error , null);
                }
                // process success
                var thumbs = [];
                var doTypeset = false;
                if(items && items.length > 0) {
                    for (var i in items){
                        var item = items[i];
                        // 只要有未生成预览图的页面就需要排版
                        if (!item.thumb || item.thumb.length <=0) {
                            doTypeset = true;
                            break;
                        }
                        thumbs.push(item.thumb);
                    }
                } else {
                    doTypeset = true;
                }
                // 构建返回值
                var data = {
                    image : {
                        thumbs : thumbs,
                        w : itemInfo.width,
                        h : itemInfo.height
                    },
                    docNm : itemInfo.doc_name||''
                };
                if(!doTypeset) {
                    return callback(error, data);
                }
                // 重新排版
                rpcFunc.yjxCreateDesignUserDocImage(docId, withWm,function (ret) {
                    // 再次获取
                    pgEntity.getPageInfoById(function (error2, items2) {
                        if (error2) {
                            console.log('yjx/v1/util/documentUtil.js [getUserDesignDocPreview] Re-getPageInfoById Err: ' + error2);
                            return callback(error2, null)
                        }
                        // process success
                        thumbs = [];
                        if (items2 && items2.length > 0) {
                            for (var n in items2) {
                                var item = items2[n];
                                // 只要有未生成预览图的页面就返回error
                                if (!item.thumb || item.thumb.length <=0) {
                                    return callback('排版失败', null);
                                }
                                thumbs.push(item.thumb);
                            }
                        } else  {
                            return callback('排版失败', null);
                        }
                        data.image.thumbs = thumbs;
                        return callback(error2, data);
                    });
                });
            });
        });
    };



    /**
     * 获取用户 ppt 作品预览数据(未排版则先排版)
     *
     * @deprecated 一键秀暂不支持 PPT
     *
     * @author 王俊
     * @date 2017-11-19
     *
     * @param userId    用户唯一标识
     * @param docId     ppt 作品唯一标识(ppt 作品表 id)
     * @param callback  回调
     *            err: 预览失败
     *            data : {
     *              image: {
     *                  "thumbs":[
     *                       "http://itbour-generate.oss-cn-hangzhou.aliyuncs.com/image/U30330/2016/11/06/091954617_IqjCfwBAzWz7I683nMRf/0.jpg"
     *                   ],
     *                  "w" : 720,
     *                  "h" : 1280
     *              }
     *              "docNm":"欢度国庆",         // 作品名称
     *           }
     */
    documentUtil.getUserPPTDocPreview = function (userId, docId, callback) {

        // 获取文档
        var docEntity = new YjxPptUserDocModel({
            doc_id:docId,
            del_flg:0
        });
        docEntity.findFromDB(function (findErr, docs) {
            if (findErr || !docs || docs.length <=0) {
                console.log('yjx/v1/util/document.js [getUserPPTDocPreview] find doc error: ' + findErr);
                return callback(findErr || '该作品不存在或已删除', null);
            }
            var userDocInfo = docs[0];

            // 获取preview
            var entity = new YjxPptUserPageModel({
                doc_ids:docId
            });
            entity.getPagesInfoByDocIds(function(error, items){
                if(error){
                    console.log('yjx/v1/util/document.js [getUserPPTDocPreview] getPagesInfoByDocIds error: '+error);
                    return callback(error, null);
                }

                var thumbs = [];
                var doTypeset = false;
                if (items && items.length > 0) {
                    for (var i in items){
                        var item = items[i];

                        // 只要有未生成预览图的页面就返回error
                        if (!item.thumb_s || item.thumb_s.length <= 0) {
                            doTypeset = true;
                            break;
                        }
                        thumbs.push(item.thumb_s);
                    }
                }
                // 如果没有页数据, 则需要排版
                else {
                    doTypeset = true;
                }
                var retData = {
                    image : {
                        thumbs : thumbs,
                        w : 1600,
                        h : 900
                    },
                    docNm : userDocInfo.doc_name
                };

                if(!doTypeset) {
                    return callback(null, retData);
                }


                // 重新排版
                rpcFunc.yjxTypesetPPTUserDoc(docId, function (ret) {
                    // 再次获取
                    entity.getPagesInfoByDocIds(function (err, items2) {
                        if (err) {
                            console.log('home.js [getDocPreviewEx] Re-getPagesInfoByDocIds error: ' + err);
                            return ret_func(0, CODE.OPERATION_FAILED);
                        }
                        // process success
                        thumbs = [];
                        if (items2 && items2.length > 0) {
                            for (var n in items) {
                                var item = items2[n];
                                // 只要有未生成预览图的页面就返回error
                                if (!item.thumb_s || item.thumb_s.length <= 0) {
                                    return callback('排版失败', null);
                                }
                                thumbs.push(item.thumb_s);
                            }
                        }
                        retData.image.thumbs = thumbs;
                        return callback(null, retData);
                    });
                });

            });
        });

    };

    /**
     * 获取用户视频作品预览信息(未排版则先排版)
     *
     * @author 王俊
     * @date 2017-11-19
     *
     * @param userId    用户唯一标识
     * @param docId     用户视频作品唯一标识(视频作品表 id)
     * @param bgId      用户视频作品背景唯一标识(竖屏作品表 id)
     * @param withWm    是否携带水印
     * @param callback  回调
     *            err: 预览失败
     *            data : {
     *              video: {
     *                   "thumbs":[
     *                       "http://itbour-generate.oss-cn-hangzhou.aliyuncs.com/image/U30330/2016/11/06/091954617_IqjCfwBAzWz7I683nMRf/0.jpg"
     *                   ],
     *                   "w" : 720,
     *                   "h" : 1280,
     *                   "videoUrl" : "http://itbour-generate.oss-cn-hangzhou.aliyuncs.com/image/U30330/2016/11/06/091954617_IqjCfwBAzWz7I683nMRf/0.mp4",
     *                   "duration" : 100,       // 视频时长, 单位:秒
     *                   "videoSize" : 4093200,  // 视频内存大小, 单位: Byte, 前端计算使用1000做进制转换, 避免出现流量显示与使用不一致的情况
     *              },
     *              "bgInfo" : {             // 视频当前背景信息, 若当前视频无背景, 此字段为空
     *                  "thumbs":[              // 当前背景图, 固定去第零张
     *                      "http://itbour-generate.oss-cn-hangzhou.aliyuncs.com/image/U30330/2016/11/06/091954617_IqjCfwBAzWz7I683nMRf/0.jpg"
     *                  ],
     *                  "w" : 720,              // 当前背景宽
     *                  "h" : 1280,             // 当前背景高
     *                  "videoFrame" : {        // 视频坑所在位置
     *                      "x" : 100,
     *                      "y" : 100,
     *                      "w" : 400,
     *                      "h" : 500
     *                  }
     *              },
     *             "docNm":"欢度国庆",         // 作品名称
     *           }
     */
    documentUtil.getUserVideoDocPreview = function (userId, docId, bgId, withWm, callback) {

        var tasks =[];
        // 1. 获取视频文档信息
        tasks.push(function (cb) {
            var videoEntity = new YjxVideoUserDocModel({
                doc_id: docId,
                user_id : userId,
                del_flg : 0
            });
            videoEntity.findFromDB(function (findErr, videos) {
                if(findErr || !videos || videos.length <=0) {
                    return cb(findErr || '该作品不存在或已删除', null);
                }
                var data = {
                    video : videos[0],          // *** 记录视频文档信息
                    dirty : videos[0].dirty     // *** 记录视频文档是否需要排版
                };
                return cb(findErr, data);
            });
        });
        // 2. 排版视频
        tasks.push(function (data, cb) {
            // 不需要排版
            if(!data.dirty) {
                data.res_low = data.video.res_low;                  // *** 记录低精度视频资源 id
                data.comb_res_low = data.video.comb_res_low;        // *** 记录低精度合并资源 id
                return cb(null, data);
            }
            // 需要排版
            rpcFunc.yjxCreateVideoUserDocVideo(docId, withWm,function (error) {
                data.needRefresh = 1;                               // *** 标记需要刷新数据
                return cb(error, data);
            });
        });
        // 3. 刷新数据(如果需要)
        tasks.push(function (data, cb) {
            if(!data.needRefresh) {
                return cb(null, data);
            }
            var videoEntity = new YjxVideoUserDocModel({
                doc_id: docId,
                user_id : userId,
                del_flg : 0
            });
            videoEntity.findFromDB(function (findErr, videos) {
                if(findErr || !videos || videos.length <=0) {
                    return cb(findErr || '该作品不存在或已删除', null);
                }
                data.video = videos[0];                             // *** 刷新视频文档信息
                data.dirty = videos[0].dirty;                       // *** 刷新视频文档是否需要排版
                data.res_low = data.video.res_low;                  // *** 刷新低精度视频资源 id
                data.comb_res_low = data.video.comb_res_low;        // *** 刷新低精度合并资源 id
                data.needRefresh = 0;                               // *** 刷新状态标记
                return cb(findErr, data);
            });
        });
        // 4. 获取视频资源
        tasks.push(function (data, cb) {
            var resEntity = new YjxVideoResModel({
                res_id : data.res_low,
                del_flg : 0
            });
            resEntity.findFromDB(function (findErr, resours) {
                if(findErr || !resours || resours.length <=0) {
                    return cb(findErr || '排版失败', null);
                }
                var res = resours[0];
                data.videoResLow = {
                    thumbs : retUtil.safe_parser_JSON_string(res.thumbs) || [],
                    w : res.w,
                    h : res.h,
                    videoUrl : res.url,
                    duration : res.duration,
                    videoSize : res.file_size
                };                                                 // *** 记录视频信息
                // // 如果存在封面信息, 则返回封面相关信息
                if(Number(data.video.cover_dur) > 0) {
                    data.videoResLow.coverInfo = {
                        cover : data.video.cover || '',
                        coverDuration : data.video.cover_dur || 0,
                        coverTime : data.video.cover_time || 0
                    };
                }
                return cb(null, data);
            })
        });
        // 5. 获取视频背景信息
        tasks.push(function (data, cb) {
            if(!bgId) {
                return cb(null, data);
            }
            // var bgWithWm = withWm;
            // 强制视频背景不带水印
            var bgWithWm = 0;
            documentUtil.getUserDesignDocPreview(userId, bgId, bgWithWm, function (error, bgInfo) {
                data.bgInfo = bgInfo;                              // *** 记录视频背景数据
                return cb(error, data);
            });
        });
        // 6. 获取视频背景中的视频位置信息
        tasks.push(function (data, cb) {
            if(!bgId) {
                return cb(null, data);
            }
            var entity = new YjxDesignUserDocModel();
            entity.getViewBgContentVideoFrame(bgId, function (error, frame) {
                data.bgInfo.videoFrame = frame;                     // *** 记录视频坑的位置
                return cb(null, data);
            })
        });
        // 7. 获取模板图替换视频作品的缩略图(如果作品有封面图, 则封面图优先)
        tasks.push(function (data, cb) {
            // 替换视频缩略图为封面图
            if(data.video.cover && data.video.cover.length >0) {
                data.videoResLow.thumbs = [data.video.cover];
                return cb(null, data);
            }
            // 没有封面图, 则取模板图代替
            var entity = new VideoDesignDocModel({
                design_id : data.video.design_id,
                del_flg : 0
            });
            entity.findFromDB(function (error, designs) {
                if(designs && designs.length >0 && designs[0].theme_thumb) {
                    data.videoResLow.thumbs = [designs[0].theme_thumb];
                }
                return cb(null, data);
            });
        });
        async.waterfall(tasks, function (error, data) {
            if(error) {
                return callback(error, null);
            }

            var retData = {
                video : data.videoResLow,
                bgInfo: data.bgInfo,
                docNm : data.video.doc_name
            };
            return callback(error, retData);
        })

    };

    /**
     * 获取 PPT 保留页信息
     *
     * @deprecated 一键秀暂不支持 PPT
     *
     * @author 严旭东
     * @date 2017-11-20
     *
     * @param tmplId: 统一模版id
     * @param callback 回调
     *              err 错误信息 若err为null则成功返回
     * */
    documentUtil.getPptBackupPage_v1_0 = function(tmplId,callback){
        var entityUtd = new YjxUniItemsModel({
            uni_item_id :tmplId,
            del_flg:0,
            item_type:20
        });
        entityUtd.findFromDB(function(err,data){
            if(err){
                return callback(err,null)
            }
            var tmpl_id = data[0].tmpl_id;
            var entity = new ItbTmplPageModel({
                tmpl_id:tmpl_id,
                backup_flg:1,
                del_flg : 0
            });

            entity.findFromDB(function(err,data){
                if(err){
                    callback(err,null)
                }
                var list = [];
                var obj = {};
                for(var i = 0;i<data.length;i++){
                    obj = {};
                    obj.thumb = data[i].thumb_s;
                    obj.base_doc_id = data[i].tmpl_id;
                    obj.base_page_id = data[i].page_id;
                    list.push(obj)
                }
                callback(null,{list:list})
            })
        });
    };



    /**
     * 获取 PPT 指定页内容
     *
     * @deprecated 一键秀暂不支持 PPT
     *
     * @author 严旭东
     * @date 2017-11-20
     *
     * @param base_page_id:ppt 保留页内返回的 base_page_id
     * @param callback 回调
     *              err 错误信息 若err为null则成功返回
     * */
    documentUtil.getPptPageConent_v1_0 = function(base_page_id,callback){
        var base_doc_id,doc_id,doc_name,ver;
        var entity = new ItbTmplPageModel({
            page_id:base_page_id,
            backup_flg:1,
            del_flg : 0
        });
        entity.findFromDB(function(err,pages){
            if(err){
                return callback(err,null)
            }
            var entityItp = new ItbTemplateModel({
                tmpl_id:pages[0].tmpl_id,
                del_flg:0
            });
            entityItp.findFromDB(function(err,data){
                if(err){
                    return callback(err,null)
                }
                base_doc_id = data[0].base_tmpl_id;
                doc_id = data[0].tmpl_id;
                doc_name = data[0].tmpl_name;
                ver = data[0].ver;
                documentUtil.processPPTPages(pages, function (processPageErr, results) {
                    if(processPageErr) {
                        return callback(processPageErr, null);
                    }
                    var retData = {
                        max_id:0,
                        base_doc_id:base_doc_id,
                        doc_id:doc_id,
                        doc_name:doc_name,
                        pages:results,
                        ver:ver
                    };
                    return callback(processPageErr, retData);
                });
            });
        })
    };


    /**
     * 获取真实模版id
     *
     * @author 严旭东
     * @date 2017-11-20
     *
     * @param tmplId:模板唯一标识
     * @param callback 回调
     *              err 错误信息 若err为null则成功返回
     *              data [19] // tmpl_id
     * */
    documentUtil.getChildTmplId = function(tmplId,callback){
        var entity = new YjxUniItemsModel({
            uni_item_id:tmplId
        });
        entity.findFromDB(function(err,data){
            if(err||data.length<=0){
                return callback(err,null)
            }
            var designId = data[0].item_id;
            return callback(null,designId)
        })
    };

    /**
     * 去除作品水印
     *
     * @author 王俊
     * @date 2017-11-21
     *
     * @param userId        用户唯一标识
     * @param uniDocId      用户统一作品标识
     * @param callback  回调
     *          err: 去水印失败
     *          data: 作品预览信息, 参照: http://114.55.172.253:7000/project/11/interface/api/97
     */
    documentUtil.removeWatermark_v1_0 = function(userId, uniDocId, callback){

        var totalTasks = [];
        // 1. 获取基础分类信息
        totalTasks.push(function (callback) {
            var entity = new YjxUniUserDocModel();
            entity.checkUniUserDocType(uniDocId,function (checkErr, typeInfo) {
                if (checkErr) {
                    return callback(checkErr, null);
                }
                var data = {};
                data.typeInfo = typeInfo;                       // *** 记录作品分类信息
                data.docId = typeInfo.doc_id;                   // *** 记录作品子表 id
                data.docType = Number(typeInfo.doc_type);       // *** 记录作品类型
                data.videoBgId = Number(typeInfo.video_bg_id);  // *** 记录作品背景 id
                data.wmPaid = Number(typeInfo.wm_paid);         // *** 记录作品当前状态是否已付费
                data.watermark = Number(typeInfo.watermark);    // *** 记录作品当前状态是否有水印
                // todo 去水印接口是否强制, 待定
                // 作品不含水印(直接转调获取当前预览信息)
                // if(watermark === 0) {
                //     return documentUtil.getDocPreview_v1_0(userId, uniDocId, callback);
                // }
                // 尚未付款
                if(data.wmPaid !== 1) {
                    return callback('尚未收到您的款项, 请稍后再试', null);
                }
                return callback(checkErr, data);
            });
        });
        // 2. 更新订单状态为完成
        totalTasks.push(function (data, callback) {
            var entity = new YjxTradeOrderModel();
            entity.updateUserWmOrderStateToCompleteByUinDocId(userId, uniDocId, function (error) {
                return callback(error, data);
            });
        });
        // 3. 调用去水印方法
        totalTasks.push(function (data, callback) {
            data.withWm = 0;                                    // *** 记录接下来的排版不带水印
            // 设计作品
            if(data.docType === 10) {
                // 去设计水印
                documentUtil.removeDesignUserDocWatermark(userId, data.docId, function (removeWmErr) {
                    return callback(removeWmErr, data);
                });
            } else  if (data.docType === 20) {
                // 暂不支持 ppt 去水印
                return callback(null, data);
            } else if(data.docType === 30) {
                documentUtil.removeVideoUserDocWatermark(userId, data.docId, data.videoBgId, function (removeWmErr) {
                    return callback(removeWmErr, data);
                })
            } else {
                return callback('暂不支持当前作品分类', data);
            }
        });
        // 4. 更新作品去水印标记
        totalTasks.push(function (data, callback) {
            var entity = new YjxUniUserDocModel({
                uni_doc_id : uniDocId,
                watermark : data.withWm,
                update_by : userId
            });
            entity.updateToDB(function (error) {
                return callback(error, data);
            });
        });
        // 5. 调用获取预览方法, 获取预览信息
        totalTasks.push(function (data, callback) {
            // 设计作品
            documentUtil.getDocPreview_v1_0(userId, uniDocId, function (error, prvInfo) {
                data.ret = prvInfo;                             // *** 记录返回值
                return callback(error, data);
            });
        });
        // 顺序处理以上步骤
        async.waterfall(totalTasks, function (error, data) {
            if(error) {
                return callback(error, null);
            }
            return callback(error, data.ret);
        })
    };
    /**
     * 去除用户设计作品水印
     *
     * @author 王俊
     * @date 2017-11-21
     *
     * @param userId    用户唯一标识
     * @param docId     设计作品唯一标识
     * @param callback  回调
     *          err: 设计作品去水印失败
     */
    documentUtil.removeDesignUserDocWatermark = function (userId, docId, callback) {
        // 重新排版
        var withwm = 0; // 不需要携带水印
        rpcFunc.yjxCreateDesignUserDocImage(docId, withwm,function (error) {
            return callback(error);
        });
    };

    /**
     * 去除用户视频作品水印
     *
     * @author 王俊
     * @date 2017-11-21
     *
     * @param userId    用户唯一标识
     * @param docId     视频作品唯一标识(视频作品表 id)
     * @param bgId      视频背景唯一标识(竖屏作品表 id)
     * @param callback  回调
     *          err: 视频作品去水印失败
     */
    documentUtil.removeVideoUserDocWatermark = function (userId, docId, bgId, callback) {

        // 背景去水印, 视频去水印
        var tasks = [];
        // 背景去水印
        tasks.push(function (callback) {
            if(!bgId) {
                return callback(null, null);
            }
            rpcFunc.yjxCreateDesignUserDocImage(bgId, 0, function (error) {
                return callback(error);
            })
        });
        // 视频去水印
        tasks.push(function (callback) {
            rpcFunc.yjxCreateVideoUserDocVideo(docId, 0, function (error) {
                return callback(error);
            })
        });
        async.parallel(tasks, function (error, results) {
            return callback(error);
        });
    };

    /**
     * 获取用户作品下载地址
     *
     * @author 王俊
     * @date 2017-11-22
     *
     * @param userId    用户唯一标识
     * @param uniDocId  作品唯一标识
     * @param quality   作品质量标记, 保留字段
     * @param downloadType 1. 下载视频带背景(若有背景), 2 仅下载小视频, 默认为1, 下载带背景的视频,注意:  当作品没有背景时此字段无效
     * @param callback  回调
     *          err:    获取失败
     *          data:   {
     *                     "docId" : 989,
     *                     "opType" : 1,               // 业务分类, 暂定如下: 1 竖屏(单页/印品等)  2 视频  3 PPT
     *                     "fileSize" : 989889,        // 文件大小, 单位: byte  换算时使用1000做转换, 避免与运营商统计不一致
     *                     "downloadUrls" : [          // 作品下载地址(可能是图片, 可能是视频等)
     *                         "http://itbour-user.oss-cn-hangzhou.aliyuncs.com/image/Unull/2017/10/31/154053345_wvk4TknmHKww7HztThwx.jpg",
     *                         "http://itbour-user.oss-cn-hangzhou.aliyuncs.com/image/Unull/2017/10/31/154053345_wvk4TknmHKww7HztThwx.jpg"
     *                     ]
     *                 }
     */
    documentUtil.getDocDownloadUrl_v1_0 = function(userId, uniDocId, quality, downloadType,callback) {

        var docEntity = new YjxUniUserDocModel();
        docEntity.checkUniUserDocType(uniDocId, function (error, typeInfo) {
            if(error){
                return callback(error,null);
            }

            var docType = Number(typeInfo.doc_type);
            var docId = Number(typeInfo.doc_id);
            var bgId = Number(typeInfo.video_bg_id);
            var watermark = Number(typeInfo.watermark);
            var wmPaid = Number(typeInfo.wm_paid);

            var withWm = !wmPaid;
            var retData = {
                docId : uniDocId
            };
            // 设计
            if(docType === 10) {
                documentUtil.getUserDesignDocDownloadUrl(userId, docId, quality, withWm, function (getUrlErr, data) {
                    if(getUrlErr) {
                        return callback(getUrlErr, null);
                    }
                    // 设计
                    retData.opType = 1; // 前端业务标记, 设计
                    retData.fileSize = data.fileSize;
                    retData.downloadUrls = data.downloadUrls;
                    return callback(getUrlErr, retData);
                });
            }
            // ppt
            else if(docType === 20) {
                documentUtil.getUserPPTDocDownloadUrl(userId, docId, quality, withWm, function (getUrlErr, data) {
                    if(getUrlErr) {
                        return callback(getUrlErr, null);
                    }
                    // 设计
                    retData.opType = 3; // 前端业务标记, ppt
                    retData.fileSize = data.fileSize;
                    retData.downloadUrls = data.downloadUrls;
                    return callback(getUrlErr, retData);
                });
            }
            // 视频
            else if(docType === 30) {
                documentUtil.getUserVideoDocDownloadUrl(userId, docId, bgId, quality, withWm, downloadType,function (getUrlErr, data) {
                    if(getUrlErr) {
                        return callback(getUrlErr, null);
                    }
                    // 设计
                    retData.opType = 2; // 前端业务标记, 视频
                    retData.fileSize = data.fileSize;
                    retData.downloadUrls = data.downloadUrls;
                    return callback(getUrlErr, retData);
                });

            }
            // 自由创建视频
            else if(docType === 40) {
                var opt = {
                    userId : userId,
                    docId : uniDocId,
                    bgId : bgId,
                    quality :quality,
                    withWm : withWm,
                    downloadType :downloadType
                };
                documentUtil.getUserCustVideoDoc(opt, function (getUrlErr, cusRes) {
                    if (getUrlErr) {
                        return callback(getUrlErr, null);
                    }
                    // 设计自由创建
                    retData.opType = 4; // 前端业务标记, 视频
                    retData.fileSize = cusRes[0].fileSize || 0;
                    retData.downloadUrls = [cusRes[0].url] || [];
                    return callback(getUrlErr, retData);
                });
            }else  {
                return callback('暂不支持此分类', null);
            }
        });
    };

    /**
     * 获取用户设计作品的下载地址
     *
     * @author 王俊
     * @date 2017-11-22
     *
     * @param userId    用户唯一标识
     * @param docId     竖屏作品唯一标识
     * @param quality   下载图质量
     * @param withWm    是否携带水印
     * @param callback  回调
     *          err: 获取下载地址失败
     *          data: {
     *                     "fileSize" : 989889,        // 文件大小, 单位: byte  换算时使用1000做转换, 避免与运营商统计不一致
     *                     "downloadUrls" : [          // 作品下载地址
     *                         "http://itbour-user.oss-cn-hangzhou.aliyuncs.com/image/Unull/2017/10/31/154053345_wvk4TknmHKww7HztThwx.jpg",
     *                         "http://itbour-user.oss-cn-hangzhou.aliyuncs.com/image/Unull/2017/10/31/154053345_wvk4TknmHKww7HztThwx.jpg"
     *                     ]
     *                 }
     */
    documentUtil.getUserDesignDocDownloadUrl = function (userId, docId, quality, withWm, callback) {
        var tasks = [];

        // 1. 先预览作品, 避免出现未排版的作品
        tasks.push(function (cb) {
            documentUtil.getUserDesignDocPreview(userId, docId, withWm, function (error, info) {
                if(error) {
                    return cb(error, null);
                }
                var data = {};
                data.previewInfo = info;        // *** 记录预览信息
                return cb(error, data);
            })
        });
        // 2. 获取下载信息
        tasks.push(function (data, cb) {
            var entity = new YjxDesignUserDocModel();
            entity.getDesignUserDocDownloadUrls(userId, docId, function (error, dInfo) {
                if(error) {
                    return cb(error, null);
                }
                data.dInfo = dInfo;                 // *** 记录初始下载信息
                data.typeL = Number(dInfo.type);    // *** 记录分类信息
                return cb(error, data);
            });
        });
        // 3. 非印品直接使用下载地址, 印品则排版高清图
        tasks.push(function (data, cb) {
            // 非印品
            if(data.typeL !== CONFIG.DOC_TYPE_4) {
                data.downloadUrls = data.dInfo.thumbs;      // 非印品则直接使用下载地址
                return cb(null, data);
            }
            // 印品, 排版高清图
            documentUtil.getUserDesignDocImagesForPrint(userId, docId, withWm, function (error, images) {
                if(error) {
                    return cb(error, null);
                }
                data.downloadUrls = images;
                return cb(error, data)
            });
        });
        async.waterfall(tasks, function (error, data) {
            if(error) {
                return callback(error, null);
            }
            var retData = {
                fileSize : 0,   // todo 是否有必要计算图片的文件大小
                downloadUrls : data.downloadUrls
            };
            return callback(error, retData);
        });
    };

    /**
     * 获取 PPT 文件下载地址
     *
     * @deprecated 一键秀暂不支持 PPT
     *
     * @author 王俊
     * @date 2017-11-22
     *
     * @param userId    用户 id
     * @param docId     用户 PPT 作品 id
     * @param quality   下载质量, 预留字段
     * @param withWm    是否携带水印
     * @param callback  回调
     *          error:  错误
     *          data: {
     *              fileSize : 1999,    ppt 文件大小
     *              downloadUrls : []   下载地址数组
     *          }
     */
    documentUtil.getUserPPTDocDownloadUrl = function (userId, docId, quality, withWm, callback) {

    };

    /**
     * 获取视频文件下载地址(有背景则合并背景)
     *
     * @author 王俊
     * @date 2017-11-22
     *
     * @param userId    用户 id
     * @param docId     视频作品 id
     * @param bgId      视频背景 id
     * @param quality   下载质量 预留
     * @param withWm    是否携带水印
     * @param downloadType 1. 下载视频带背景(若有背景), 2 仅下载小视频, 默认为1, 下载带背景的视频,注意:  当作品没有背景时此字段无效
     * @param callback  回调
     *          error: 错误
     *          data: {
     *              fileSize : 文件大小, 单位: byte
     *              downloadUrls : [] 下载地址数组
     *          }
     */
    documentUtil.getUserVideoDocDownloadUrl = function (userId, docId, bgId, quality, withWm, downloadType,callback) {

        var tasks = [];

        // 获取作品信息
        tasks.push(function (callback) {
            var videoEntity = new YjxVideoUserDocModel({
                doc_id : docId,
                user_id : userId,
                del_flg : 0
            });

            videoEntity.findFromDB(function (findErr, videos) {
                if(findErr || !videos || videos.length <=0) {
                    return callback(findErr || '该作品不存在或已删除', null);
                }
                var data = {};
                data.video = videos[0];
                if(Number(data.video.dirty) === 1) {
                    return callback('该作品尚未预览', null);
                }
                // 如果下载选项为2, 标记不需要合并视频
                if(!bgId || downloadType === 2) {
                    data.resId = Number(data.video.res_low);
                } else  {
                    data.resId = Number(data.video.comb_res_low);
                }
                return callback(findErr, data);
            });
        });
        // 如果不存在, 则生成
        tasks.push(function (data, callback) {
            if(data.resId && data.resId > 0) {
                return callback(null, data);
            }
            if(!bgId) {
                rpcFunc.yjxCreateVideoUserDocVideo(docId, withWm, function (error, result) {
                    data.needRefresh = 1;
                    return callback(error, data);
                });
            } else {
                rpcFunc.yjxCreateVideoUserDocVideoWithBg(docId, withWm, function (error, result) {
                    data.needRefresh = 1;
                    return callback(error, data);
                });
            }
        });

        // 如果需要刷新则刷新
        tasks.push(function (data, callback) {
            if(!data.needRefresh) {
                return callback(null, data);
            }
            var videoEntity = new YjxVideoUserDocModel({
                doc_id : docId,
                user_id : userId,
                del_flg : 0
            });
            videoEntity.findFromDB(function (findErr, videos) {
                if(findErr || !videos || videos.length <=0) {
                    return callback(findErr || '该作品不存在或已删除', null);
                }
                data.video = videos[0];
                if(Number(data.video.dirty) === 1) {
                    return callback('该作品尚未预览', null);
                }
                if(!bgId) {
                    data.resId = data.video.res_low;
                } else  {
                    data.resId = data.video.comb_res_low;
                }
                return callback(findErr, data);
            });
        });

        // 获取资源信息
        tasks.push(function (data, callback) {
            var entity = new YjxVideoResModel({
                res_id : data.resId,
                del_flg : 0
            });
            entity.findFromDB(function (error, resources) {
                if(error || !resources || resources.length <=0) {
                    return callback(error || '视频资源不存在或已删除', data);
                }
                data.res = resources[0];
                return callback(error, data);
            })
        });
        async.waterfall(tasks, function (error, data) {
            if(error) {
                return callback(error, null);
            }
            var retData = {
                fileSize : data.res.file_size || 0,
                downloadUrls : [data.res.url]
            };
            return callback(error, retData);
        });
    };
    /**
     * 为用户设计作品排版出用于印刷的图片
     *
     * @author 王俊
     * @date 2017-11-21
     *
     * @param userId    用户作品 id
     * @param docId     设计作品 id(印品)
     * @param withWm    是否携带水印
     * @param callback  回调
     *          error:  生成失败
     *          images: []  图片下载数组
     */
    documentUtil.getUserDesignDocImagesForPrint = function (userId, docId, withWm, callback) {
        rpcFunc.yjxCreateImageForPrint(docId, withWm, 1, function (error, images) {
            return callback(error, images);
        });
    };
    /**
     * 查询用户设计作品是否支持 HQ 下载
     *
     * @author 王俊
     * @date 2017-11-28
     *
     * @param docId     用户设计作品 id
     * @param callback  回调
     *          err: 查询出错
     *          supportHQ: 0/1 是否支持高清下载
     */
    documentUtil.ckeckUserDesignDocSupportHQ = function (docId, callback) {
        var entity = new YjxDesignUserDocModel({
            doc_id : docId,
            del_flg : 0
        });
        entity.findFromDB(function (error, docs) {
            if(error || !docs || docs.length <= 0) {
                return callback(error || '该作品不存在或已删除', null);
            }
            var doc = docs[0];
            var type_id = doc.type_id;

            var typeEntity = new TgTypeModel({
                type_id : type_id,
                del_flg : 0
            });
            typeEntity.findFromDB(function (error, types) {
                if(error || !types || types.length <= 0) {
                    return callback(error || '该分类不存在或已删除', null);
                }
                var type = types[0];
                var supportHQ = Number(type.top_parent) === CONFIG.DOC_TYPE_4 ? 1 : 0;
                return callback(error, supportHQ);
            })
        });
    };


    /**
     * 修改表单使用状态
     *
     * @author 毛凯
     * @date 2017-12-12
     *
     * @param userId    用户 id
     * @param docId     用户统一作品id
     * @param formState    是否携带水印
     * @param callback  回调
     *          error:  返回错误信息
     *          data:  成功返回{}
     */
    documentUtil.changeFormState_v1_0 = function (userId,docId,formState, callback) {
        var entity = new YjxUniUserDocModel({
            uni_doc_id : docId,
            update_by : userId,
            form_flg : formState
        });
        entity.updateToDB(function (error, docs) {
            if(error) {
                return callback(error, null);
            }
            return callback(null,{});
        });
    };

    /**
     * 获取作品表单信息
     *
     * @author 毛凯
     * @date 2017-12-12
     *
     * @param userId    用户 id
     * @param docId     用户统一作品id
     * @param callback  回调
     *          error:  返回错误信息
     *          data:  {
     *               "success" : 1,
     *               "msg" : "成功",
     *               "data" : {
     *                   "formInfo":{                        //表单信息
     *                       "form_type":"1",
     *                       "key1":"电话",
     *                       "key2":"姓名",                 //thumb为表单样式图
     *                       "thumb":"http://itbour-generate.oss-cn-hangzhou.aliyuncs.com/image/U30330/2016/11/06/091954617_IqjCfwBAzWz7I683nMRf/0.jpg"
     *                   },
     *                   "formState":1,                      // 表单状态 0 不设置 1.开启  2.关闭
     *                   "fromCust":"",                      // 自定义反馈模版 例 "['电话','姓名']"
     *                   "formId":1,                         // 表单模版id
     *               }
     *           }
     */
    documentUtil.getDocFormInfo_v1_0 = function (userId,docId, callback) {
        //1，用 docId userId去yjx_user_uni_doc去form相关字段
        var entity = new YjxUniUserDocModel({
            uni_doc_id : docId
        });
        var data ={};
        entity.findFromDB(function (error, docs) {
            if(error || !docs || docs.length <=0) {
                return callback(error || '当前作品不存在或已删除', null);
            }
            var formState = docs[0].form_flg;
            var formCust = docs[0].form_cust;
            var formId = docs[0].form_id;
            var form_name = docs[0].form_name;

            var formInfo= {};
            data = {
                formState:formState,                      // 表单状态 0 不设置 1.开启  2.关闭
                formCust: formCust,                      // 自定义反馈模版 例 "['电话','姓名']"
                formId:formId,
                formInfo :formInfo,
                form_name : form_name                   // 表单标题
            };
            if(formId && formId > 0 ){
                var formTmplEntity = new YjxFormTmplModel({
                    form_id : formId
                });
                //2.通过formID查询tmplform
                formTmplEntity.findFromDB(function (error, res) {
                    if (error) {
                        return callback(error, null);
                    }
                    if(res && res.length > 0) {
                        data.formInfo = res[0];
                    }
                    return callback(null, data);
                });
            }else {
                return callback(null, data);
            }
        });
    };

    /**
     * 修改表单使用状态
     *
     * @author 毛凯
     * @date 2017-12-12
     *
     * @param userId    用户 id
     * @param docId     用户统一作品id
     * @param formInfo  表单信息的json字符串
     * @param formId    反馈模版唯一标识
     * @param callback  回调
     *          error:  返回错误信息
     *          data:  成功返回{}
     */
    documentUtil.submitFormInfo_v1_0 = function (userId,docId,formInfo,formId, callback) {
        var info_type = 10;
        if(formId<=0 || !formId){
            info_type= 20;
        }
        var entity = new YjxFormInfoModel({
            uni_doc_id : docId,
            user_id : userId,
            form_id : formId,
            info_type:info_type,
            update_by : userId,
            form_name : formInfo.form_name || '我要报名'
        });

        for(var i=1;i<=10;++i){
            var key = "key"+i;
            if(formInfo[key]){
                entity[key] = formInfo[key];
            }
            var value = "value"+i;
            if(formInfo[value]){
                entity[value] = formInfo[value];
            }
        }
        entity.saveToDB(function (error, docs) {
            if(error) {
                return callback(error, null);
            }
            return callback(null,{});
        });
    };

    /**
     * 修改表单使用状态
     *
     * @author 毛凯
     * @date 2018-1-22
     *
     * @param userId     用户 id
     * @param docId      用户统一作品id
     * @param bgTmplId      视频背景模板唯一标识 uni_item_id
     * @param bgString   背景 json 字符串
     * @param callback   回调
     *          error:  返回错误信息
     *          data:  成功返回{}
     */
    documentUtil.updateVideoDocBg_v1_2 = function (userId,docId,bgTmplId,bgString, callback) {
        var item = new YjxUniItemsModel({
            uni_item_id:bgTmplId,
            del_flg : 0
        });
        var tasks = [];
        //获取当前视频背景模版信息
        tasks.push(function (callback) {
            item.findFromDB(function (findDesignErr, results) {
                if (findDesignErr || !results || results.length <= 0) {
                    return callback(findDesignErr || '该模板不存在或已下架', null);
                }
                var data = {};
                data.designInfo = results[0];
                return callback(findDesignErr, data);
            });
        });

        tasks.push(function (data,callback) {
            //判断作品类型,如果是视频作品判断是否有背景id,没有创建 ,有则替换
            var designId = data.designInfo.uni_item_id;
            if(!designId){
                return callback(null,data);
            }
            var entity = new YjxUniUserDocModel();
            entity.checkUniUserDocType(docId,function (checkErr, typeInfo) {
                if (checkErr) {
                    return callback(checkErr, null);
                }
                data.typeInfo = typeInfo;
                return callback(null, data);
            });
        });

        // 如果存在, 则更新
        tasks.push(function (data,callback) {
            if(!data.typeInfo.video_bg_id){
                return callback(null,data);
            }
            var video_bg_id = data.typeInfo.video_bg_id; // 子表 id
            //替换(先删除再新增)
            documentUtil.deleteDesignUserDoc(userId,video_bg_id,function(err){
                if(err){
                    return callback(err,{});
                }
                documentUtil.enptyVideoCombRes_v1_0(userId,docId,function(updateErrMsg){
                    if(updateErrMsg){
                        return callback(updateErrMsg,{});
                    }
                    //新增设计作品文档
                    documentUtil.newDesignUserDoc(userId, docId, bgTmplId, bgString, function(err02,results02){
                        if(err02) {
                            return callback(err02, null);
                        }
                        data.newBgres = results02;
                        return callback(err02,data);
                    })
                })
            })

        });

        //没有背景进行新增背景
        tasks.push(function (data,callback) {
            if(data.typeInfo.video_bg_id) {
                return callback(null, data);
            }
            //新增设计作品文档
            documentUtil.newDesignUserDoc(userId, docId, bgTmplId, bgString, function(err02,results02){
                if(err02) {
                    return callback(err02, null);
                }
                data.newBgres = results02;
                return callback(err02,data);
            });
        });

        //处理结果
        async.waterfall(tasks, function (error, data) {
            if(error) {
                return callback(error, null);
            }
            return callback(error, data);
        });
    };


    /**
     * 获取背景模板信息Id
     *
     * @author 毛凯
     * @date 2018-1-22
     *
     * @param userId     用户 id
     * @param docId      用户作品唯一标识/视频背景模板的唯一标识
     * @param callback   回调
     *          error:  返回错误信息
     *           data : {
     *            "success" : 1,                  // 0 标识请求失败, 1 标识请求成功
     *            "msg" : "成功",                 // 如请求失败, 则为失败原因
     *            "data" : {
     *                "bgId" : 123,               // 视频背景对应的模板的统一商品 id (uni_item_id)
     *                "designId":4857,
     *                "typeL":6,
     *                 "designNm":"黑色炫酷简洁微商名片",
     *                "bleedWidth":0,
     *                "bleedHeight":0,
     *                "pageHeight":1280,
     *                "pageWidth":720,
     *                "productId":0,
     *                "productNm":null,
     *                 "videoFrame": {
     *                    "ct": 2,
     *                    "x": 0,
     *                    "y": 501.183,
     *                    "an": 0,
     *                    "w": 720,
     *                    "h": 405
     *                },
     *                "coreStructure":{
     *                    "ct":903,
     *                    "name":"微商名片",
     *                    "root":{},          // SJGTGNode 结构模型, 详情见 STGNode
     *                    "version":3
     *                },
     *                "textObjects":"",       // 设计微调信息
     *                "printPxH":1280,
     *                "printPxW":720,
     *                "hash_tag":"[5,-1,-1,30,-1,1,-1,-1,-1,-1,-1,-1]",
     *            }
     *        }
     */
    documentUtil.getDesignDocContent = function (userId,docId,callback) {
        //通过bgId获取模板核心数据
        var type_id = 1030;
        var item = new YjxUniItemsModel({
            uni_item_id : docId,
            del_flg : 0
        });
        //获取当前视频背景模版信息
        item.findFromDB(function (findDesignErr, results) {
            if (findDesignErr || !results || results.length <= 0) {
                return callback(findDesignErr || '该模板不存在或已下架', null);
            }
            var designId = results[0].item_id;
            tg3Util.getTgAndFineTuneInfoOfDesign(type_id, designId, function (getDesignErr01, data01) {
                if (getDesignErr01) {
                    console.log("documentUtil.js YjxUniItemsModel [getTgAndFineTuneInfoOfDesign] err" + getDesignErr01);
                    return callback(getDesignErr01, null);
                }
                if (!data01 && !data01.constructor) {
                    return callback("没有获取到相应模板信息", null);
                }
                data01.coreStructure = retUtil.safe_parser_JSON_string(data01.coreStructure);
                data01.bgTmplId = docId;
                return callback(getDesignErr01, data01);
            });
        });
    };


    /**
     * 获取背景模板信息Id
     *
     * @author 毛凯
     * @date 2018-1-22
     *
     * @param userId     用户 id
     * @param docId      用户作品唯一标识/视频背景模板的唯一标识
     * @param callback   回调
     *          error:  返回错误信息
     *           data : {
     *            "success" : 1,                  // 0 标识请求失败, 1 标识请求成功
     *            "msg" : "成功",                 // 如请求失败, 则为失败原因
     *            "data" : {
     *                "bgId" : 123,               // 视频背景对应的模板的统一商品 id (uni_item_id)
     *                "designId":4857,
     *                "typeL":6,
     *                 "designNm":"黑色炫酷简洁微商名片",
     *                "bleedWidth":0,
     *                "bleedHeight":0,
     *                "pageHeight":1280,
     *                "pageWidth":720,
     *                "productId":0,
     *                "productNm":null,
     *                 "videoFrame": {
     *                    "ct": 2,
     *                    "x": 0,
     *                    "y": 501.183,
     *                    "an": 0,
     *                    "w": 720,
     *                    "h": 405
     *                },
     *                "coreStructure":{
     *                    "ct":903,
     *                    "name":"微商名片",
     *                    "root":{},          // SJGTGNode 结构模型, 详情见 STGNode
     *                    "version":3
     *                },
     *                "textObjects":"",       // 设计微调信息
     *                "printPxH":1280,
     *                "printPxW":720,
     *                "hash_tag":"[5,-1,-1,30,-1,1,-1,-1,-1,-1,-1,-1]",
     *            }
     *        }
     */
    documentUtil.getVideoBgInfo_v1_2 = function (userId,docId,callback) {
        var entity = new YjxUniUserDocModel();
        entity.checkUniUserDocType(docId,function (checkErr, typeInfo) {
            if (checkErr) {
                return callback(checkErr, null);
            }
            if(!typeInfo.video_bg_id) {
                return callback("未检索到对应背景作品文档", {});
            }
            var video_bg_id = typeInfo.video_bg_id; // 子表 id
            //获取设计作品的核心数据
            documentUtil.getDesignUserDocContent(video_bg_id, userId, function (getDocErr, data) {
                if (getDocErr) {
                    return callback(getDocErr, null);
                }
                if(!data){
                    return callback("为找到对应的模板信息", {});
                }
                data.coreStructure = retUtil.safe_parser_JSON_string(data.coreStructure);

                if(typeInfo.bg_design_id && typeInfo.video_bg_type == 10) {
                    var itemId = typeInfo.bg_design_id;
                    var itemType = typeInfo.video_bg_type;
                    (new YjxUniItemsModel).getUniItemId(itemId, itemType, function (err, res) {
                        if (err) {
                            console.log("documentUtil.js YjxUniItemsModel [getUniItemId] err" + err);
                            return callback(err);
                        }
                        data.bgTmplId = res[0].uni_item_id;
                        return callback(err, data);
                    });
                }
            });
        })
    };

    /***
     * 获取指定范围模板组内模板列表
     *
     * @author 毛凯
     * @date 2017-1-31
     *
     * @param setIds 模板组 id 数组
     * @param tmplTypes 0 代表普通模板, 10 代表 vip 模板, 不传默认为 [0], 标记只获取普通模板 modify by wangjun 2018-03-23
     * @param keyword 去表情换行等特殊字符, 字符数0-30, 若为空字符串则此条件失效, 默认为空字符串
     * @param pageNum 页码
     * @param pageSize 页容量
     * @param withTotalPage 是否需要总页数
     * @param callback 回调
     *          err: 查询出错
     *          data:{
     *              list : [{
     *                      "id":1999,
     *                      "opType":1,         // 业务分类 暂定如下: 1 竖屏类型(单页/印品), 2 视频类型, 3 ppt 类型
     *                      "typeDesc":"优惠券",
     *                      "name":"创意少儿书法培训优惠券",
     *                      "thumb":"http://itbour-generate.oss-cn-hangzhou.aliyuncs.com/image/U408535/2017/11/07/143418993_uEuOZh77Qw0kIiwtXmCQ/0.jpg",
     *                      "useCounts":3697,
     *                      "w":1537,
     *                      "h":496,
     *                      "author":"李国梅",
     *                      "time":"2017-11-05 13:42:41",
     *              }],
     *              totalPage : 1   // 如果需要请求, 则返回此字段
     *          }
     */
    documentUtil.getTmplSetContentForWeb_v1_0 = function(setIds, tmplTypes, keyword,pageNum, pageSize, withTotalPage,durations,sizeIds, callback) {

        // 使用搜索缓存(老接口)
        //luaUtil.searchUniItemsFromRedis([], keyword, setIds, 4/*按 order, updateTime 排序*/, pageNum, pageSize, function (error, data) {
        //    return callback(error, data);
        //});
        // 分词操作
        var kwds = documentUtil.doSegmentOfText(keyword);
        var param={
            showTypes : [],
            keyword : kwds,
            setIds : setIds,
            orderBy : 4,
            pageNum : pageNum,
            pageSize : pageSize,
            withTotalPage : withTotalPage,
            tmplTypes : tmplTypes,
            durations : durations,
            sizeIds : sizeIds
        };

        luaUtil.searchUniItemsFromRedis(param,callback);
//        javaSearchProjectUtil.searchUniItemsFromJavaRedis(param, function (error, List) {
//            if(error){
//                console.log("luaUtil.js [searchUniItemsFromJavaRedis] err"+error);
//                return callback("没有获取到数据",{});
//            }
//            if(!List){
//                return callback("没有获取到数据",{});
//            }
//            if(List.data.list.length <= 0){
//                return callback(null,List.data);
//            }
//            for(var i = 0;i < List.data.list.length ; i++){
//                if(List.data.list[i].setId != setIds[0] && setIds.length == 1){
//                    List.data.list[i].setId = setIds[0];
//                }
//            }
//            return callback(null,List.data);
//        });


        // // 1. 获取列表
        // var entity = new YjxTmplSetModel();
        // entity.getTmplSetsContentList(setIds, pageNum, pageSize,function (getListErr, list) {
        //     if(getListErr) {
        //         return callback(getListErr, null);
        //     }
        //     // 2. 不需要总页数, 直接返回
        //     if(!withTotalPage) {
        //         return callback(getListErr, {list:list});
        //     }
        //     // 3. 需要取总页数查询总页数
        //     entity.getTmplSetsContentListCnt(setIds, function (getCntErr, count) {
        //         if(getCntErr) {
        //             return callback(getCntErr, null);
        //         }
        //         var totalPage = Math.floor((count-1)/pageSize)+1;
        //         return callback(getCntErr, {list:list, totalPage : totalPage});
        //     });
        // })
    };

    /**
     * 分词, 在 luaUtil 中也有一份, 重复是为了避免 util 间相互引用
     *
     * @author 王俊
     * @date 2017-11-27
     *
     * @param txt 待分词内容
     * @param min 可分词的最小长度, 默认2
     * @param max 可分词的最大程度, 默认6
     * @return 分词结果, 字符串数组
     */
    documentUtil.doSegmentOfText = function(txt,min,max){
        if(!txt)    return null;
        // 只能2-6个字以内分词
        min = min || 1;
        max = max || 10;
        if(txt.length>max || txt.length<min){
            return [txt];
        }
        var segs = segment.doSegment(txt);
        var segWords=[];
        for(var i=segs.length-1 ; i>=0;i--){
            var one = segs[i];
            if(one.p !== POSTAG.D_W){//过滤掉标点符号
                // 过滤掉部分词语，例如：色
                var w = one.w.replace(/色/g,'');
                segWords.push(w);
            }
        }
        segWords.push(txt);
        return segWords;
    };


    /**
     * 设置/更新视频作品封面_APP_1_3
     *
     * @author 毛凯
     * @date 2018-3-1
     *
     * @param userId     用户 id
     * @param docId      用户视频作品统一作品 id
     * @param coverTime     视频封面的 oss 链接地址
     * @param callback   回调
     *          error:  返回错误信息
     *          data : {}
     */
    documentUtil.setVideoUserDocCover_v1_3 = function (userId,docId,coverTime,callback) {
        var entity = new YjxUniUserDocModel();
        entity.checkUniUserDocType(docId,function (checkErr, typeInfo) {
            if (checkErr) {
                return callback(checkErr, null);
            }
            if(!typeInfo || typeInfo.doc_id <=0){
                return callback("添加封面失败!为获取到该作品docId", null);
            }
            var entity2 =new   YjxVideoUserDocModel({
                doc_id : typeInfo.doc_id,
                user_id : userId,
                cover_dur : 0.4, //占时写死
                cover_time : coverTime || 0,
                modify_cnt : typeInfo.modify_cnt + 1,
                res_low : 0,
                comb_res_low : 0, // updateToDB 值不能为 null
                res_mid : 0,
                comb_res_mid : 0,
                res_high : 0,
                comb_res_high : 0,
                dirty : 1,
                state : 0     // add by wangjun 2018-03-28 0待生成, 1生成中, 2生成失败, 3生成成功
            });
            entity2.updateToDB(function (error) {
                // 待生成状态, 清空 redis 标记
                VideoRenderLuadUtil.lua_video_delete_render(typeInfo.doc_id, function (delErr) {
                    if(delErr) {
                        console.log('VideoRenderLuadUtil.lua_video_delete_render: ' + delErr);
                    }
                    return callback(error,{});
                });
            });
        });
    };

    /**
     * 删除视频作品封面_APP_1_3
     *
     * @author 毛凯
     * @date 2018-3-1
     *
     * @param userId     用户 id
     * @param docId      用户视频作品统一作品 id
     * @param callback   回调
     *          error:  返回错误信息
     *          data : {}
     */
    documentUtil.removeVideoUserDocCover_v1_3 = function (userId,docId,callback) {
        var entity = new YjxUniUserDocModel();
        entity.checkUniUserDocType(docId,function (checkErr, typeInfo) {
            if (checkErr) {
                return callback(checkErr, null);
            }
            if(!typeInfo || typeInfo.doc_id <=0){
                return callback("移除封面失败!为获取到该作品docId", null);
            }
            var entity2 =new   YjxVideoUserDocModel({
                doc_id : typeInfo.doc_id,
                user_id : userId,
                cover : "",
                cover_dur : 0, //占时写死
                cover_time : 0,
                modify_cnt : typeInfo.modify_cnt + 1,
                res_low : 0,
                comb_res_low : 0, // updateToDB 值不能为 null
                res_mid : 0,
                comb_res_mid : 0,
                res_high : 0,
                comb_res_high : 0,
                dirty : 1
            });
            entity2.updateToDB(function (error) {
                return callback(error,{});
            });
        });

    };

    /**
     * 获取用户作品当前状态
     *
     * @author 王俊
     * @date 2018-03-05
     *
     * @param userId    用户 id
     * @param uniDocId  作品 id
     * @param callback  回调
     *          error
     *          status : {
     *              "id":4903,                  // 作品唯一标识
                    "opType":1,                 // 业务分类, 暂定如下: 1 竖屏(单页/印品等)  2 视频  3 PPT
                    "watermark" : 1,            // 作品是否包含水印,
                    "watermarkPay":0,           // 用户是否已支付去水印的金额
                    "formState": 1,             // 表单状态, 1:使用表单(开启), 0:使用表单(关闭)
                    "showFormFb" : 1,           // 是否显示表单反馈, 0 不显示, 1 显示
     *          }
     *
     */
    documentUtil.getDocCurrentStatus_v1_3 = function(userId, uniDocId, callback){

        var tasks = [];

        // 1. 查询基本信息
        tasks.push(function (callback) {
            var uniDoc = new YjxUniUserDocModel();
            uniDoc.checkUniUserDocType(uniDocId, function (checkErr, typeInfo) {
                if(checkErr) {
                    return callback(checkErr, null);
                }
                var status = {};
                status.id = typeInfo.uni_doc_id;
                if(Number(typeInfo.doc_type) === 10) {      // 设计
                    status.opType = 1
                }
                if(Number(typeInfo.doc_type) === 20) {      // ppt
                    status.opType = 3
                }
                if(Number(typeInfo.doc_type) === 30) {      // 视频
                    status.opType = 2
                }
                status.watermark = typeInfo.watermark;
                status.watermarkPay = typeInfo.wm_paid;
                status.formState = Number(typeInfo.form_flg) === 1 ? 1 : 0;     // 表单状态, 1:使用表单(开启), 2:使用表单(关闭)
                status.showFormFb = Number(typeInfo.form_flg) === 0 ? 0 : 1;    // 是否显示表单反馈, 0 不显示, 1 显示, 开启过就显示
                status.docId = typeInfo.doc_id;
                status.designId = typeInfo.doc_design_id;
                status.userId = typeInfo.user_id;
                if (Number(status.userId) !== Number(userId)) {
                    return callback('非本账户作品, 无法查看', null);
                }
                return callback(checkErr, status)
            });
        });

        // 2. 查询状态信息
        tasks.push(function (data, callback) {
            VideoRenderLuadUtil.lua_video_get_state(data.docId, function (getStateErr, state) {
                data.generateStatus = state;    //0待生成, 1生成中、2生成失败、3生成成功
                return callback(null, data);
            });
        });
        // 3. 如果 redis 查询失败, 从数据库查
        tasks.push(function (data, callback) {
            if (data.generateStatus === 1 || data.generateStatus === 2 || data.generateStatus === 3) {
                return callback(null, data);
            }
            var entity = new YjxVideoUserDocModel({
                doc_id : data.docId,
                del_flg : 0
            });
            entity.findFromDB(function (findErr, docs) {
                if (findErr || !docs || docs.length <=0) {
                    return callback(findErr || '该作品不存在或已删除', null);
                }
                var userDoc = docs[0];
                // 取 db 状态
                data.generateStatus = Number(userDoc.state);
                // 若 db 状态生成完成, 但是没有资源 id, 则强制指定状态为待生成
                if (data.state === 3 && userDoc.res_low <=0 && userDoc.res_mid <=0 && userDoc.res_high <=0) {
                    data.generateStatus = 0;
                }
                return callback(findErr, data);
            });
        });
        // 4. 查询作品对应模板是否为 vip
        tasks.push(function (data, callback) {
            var entity = new VideoDesignDocModel({
                design_id : data.designId
            });
            entity.findFromDB(function (findErr, designs) {
                if(findErr || !designs || designs.length <=0) {
                    return callback(findErr || '该作品对应模板不存在或已删除', null);
                }
                data.designVip = designs[0].vip;
                return callback(findErr,data);
            })
        });
        async.waterfall(tasks, function (error, data) {
            return callback(error, data);
        });
    };

    /**
     * 请求用户排版信息
     *
     * @author 王俊
     * @date 2018-03-26
     *
     * @param {Object} options              作品唯一标识
     * @param {Number} options.uniDocId     用户唯一标识
     * @param {Number} options.userId       用户唯一标识
     * @param {Number} [options.wait]       用户唯一标识
     * @param {Number} [options.device]     设备唯一标识
     * @param {Function} callback   回调
     *                      err:    获取失败
     *                      data:   获取成功
     */
    documentUtil.requestUserDocPrivewInfo_web_v1_1 = function(options, callback){

        var tasks = [];
        // 1. 查询作品当前生成状态
        tasks.push(function (callback) {
            var opt = {uniDocId : options.uniDocId};
            documentUtil.getUserVideoDocBaseInfoFromDB(opt, function (getStatusErr, statusInfo) {
                if(getStatusErr) {
                    return callback(getStatusErr, null);
                }
                var data = {};
                data.docInfo = statusInfo;
                data.coverInfo = statusInfo.coverInfo;
                delete data.docInfo.coverInfo;
                data.id = data.docInfo.id;
                if(Number(data.docInfo.userId) !== options.userId) {
                    return callback('非本账户作品, 无法查看', data);
                }
                return callback(getStatusErr, data);
            });
        });
        // 2. 如果需要排版, 则发起排版
        tasks.push(function (data, callback) {
            if(Number(data.docInfo.generateStatus) !== 0) { // 待生成
                return callback(null,data);
            }
            // 发起排版请求
            var withWm = data.docInfo.watermarkPay ? 0 : 1;
            var quality = withWm ? 1 : 2;   // 带水印的就设为高清, 否则为标清(超清生成失败)
            var estimatedDuration = data.docInfo.estimatedDuration || 10;     // 预计10s, 等待生成完成
            data.needRefresh = false;
            // 暂定阀值小于5s 的生成就等待
            var renderOpts = {
                docId : data.docInfo.docId,
                withWm : withWm,
                quality : quality,
            };
            if (options.wait && estimatedDuration < 5) {
                // rpc
                rpcFunc.yjxCreateUserVideoDocVideoWithParam(renderOpts,function (error) {
                    if (error) {
                        return callback(error);
                    }
                    data.needRefresh = true;
                    data.docInfo.generateStatus = 1;    // 修改为生成中状态
                    return callback(error, data);
                });
            } else {
                // 异步排版不等待
                rpcFunc.yjxCreateUserVideoDocVideoWithParam(renderOpts,function (error) {
                    console.log('rpcFunc.yjxCreateUserVideoDocVideoWithParam: ' + error);
                });
                data.docInfo.generateStatus = 1;    // 修改为生成中状态
                return callback(null, data);
            }
        });
        // 3. 如果需要刷新作品信息(等待排版完成), 则重新获取作品信息
        tasks.push(function (data, callback) {
            if(!data.needRefresh) {
                return callback(null, data);
            }
            var entity = new YjxVideoUserDocModel({
                doc_id : data.docId,
                del_flg : 0
            });
            entity.findFromDB(function (findErr, docs) {
                if (findErr || !docs || docs.length <=0) {
                    return callback(findErr || '该作品不存在或已删除', null);
                }
                var userDoc = docs[0];
                data.docInfo.res_low = userDoc.res_low;
                data.docInfo.comb_res_low = userDoc.comb_res_low;
                data.docInfo.res_mid = userDoc.res_mid;
                data.docInfo.comb_res_mid = userDoc.comb_res_mid;
                data.docInfo.res_high = userDoc.res_high;
                data.docInfo.comb_res_high = userDoc.comb_res_high;
                if (Number(userDoc.cover_dur) > 0) {
                    data.coverInfo = {
                        cover : userDoc.cover,
                        coverDuration : userDoc.cover_dur,
                        coverTime : userDoc.cover_time
                    };
                }
                if(!findErr) {
                    data.docInfo.generateStatus = 3;    // 修改为生成完成
                }
                return callback(findErr, data);
            });
        });
        // 4. 若作品生成完成且已付款(已去水印), 则更新订单状态
        tasks.push(function (data, callback) {
            if (data.docInfo.watermarkPay && Number(data.docInfo.generateStatus) === 3) {
                var entity = new YjxTradeOrderModel();
                entity.updateUserWmOrderStateToCompleteByUinDocId(options.userId, options.uniDocId, function (error) {
                    return callback(error, data);
                });
            } else {
                return callback(null,data);
            }
        });
        // 5. 按需获取进度信息
        tasks.push(function (data, callback) {
            if(Number(data.docInfo.generateStatus) !== 1) { // 不是生成中
                return callback(null,data);
            }
            var opts = {
                docId : data.docInfo.docId,
                estimateDuration : data.docInfo.estimatedDuration
            };
            documentUtil.getUserVideoDocProgressInfo(opts, function (error, progressInfo) {
                if (error) {
                    return callback(error, data);
                }
                console.log('getUserVideoDocProgressInfo: ' + JSON.stringify(progressInfo));
                data.progressInfo = progressInfo;
                /**
                 * @warning  去水印补丁
                 *
                 * 去水印支付完成作品状态重置为生成中
                 * 但 redis 相关记录尚未清空, 此时 redis 记录进度为 100
                 * 识别此种情况, 重置相关字段
                 *
                 * add by 王俊 2018-04-02
                 * */
                if(data.docInfo.generateStatus === 1 && data.progressInfo.progress === 100 && data.docInfo.watermarkPay === 1) {
                    data.progressInfo.progress = 0;
                    data.progressInfo.currentDuration = 0;
                    data.progressInfo.estimatedProgress = 10;
                }
                return callback(error, data);
            });
        });
        // 6. 异常逻辑, 若检测到生成时间过长, 则认定生成失败
        tasks.push(function (data, callback) {
            if(Number(data.docInfo.generateStatus) !== 1) { // 不是生成中
                return callback(null,data);
            }
            var estimatedDuration = data.progressInfo.estimatedDuration;
            var currentDuration = data.progressInfo.currentDuration;

            var limit = estimatedDuration * 3;
            if(CONFIG.DEBUG!=0){// 测试环境下的limit比正式环境大
                limit = estimatedDuration * 8;
            }else{
                limit = estimatedDuration * 7;
            }
            limit = limit < 30 ? 30 : limit;
            if (currentDuration <= limit) {
                return callback(null,data);
            }

            // 异常生成状态, 强制置为生成状态
            var opt = {
                uniDocId : options.uniDocId,
                docId : data.docInfo.docId,
                userId : options.userId
            };
            documentUtil.setVideoUserDocStateGenerateStatusFail(opt, function (error, result) {
                if(error) {
                    return callback(error, data);
                }
                data.docInfo.generateStatus = 2; // 强制置为生成失败
                return callback(error, data);
            });
        });
        // 7. 按需获取失败的预览信息
        tasks.push(function (data, callback) {
            if(Number(data.docInfo.generateStatus) !== 2) { // 不是生成失败
                return callback(null,data);
            }
            if (options.device === 600) {
                data.previewInfo = {
                    video:{
                        thumbs:["http://itbour-user.oss-cn-hangzhou.aliyuncs.com/images/U2/2018/04/03/153525618_zd9GDi0wHt/weErr.png"],
                        videoUrl : "http://itbour-user.oss-cn-hangzhou.aliyuncs.com/custAni/assets/images/U2/2018/04/03/142154482_aKQuPU8MOL/webErr.mp4",
                        duration : 100, videoSize : 241000, w:1920, h:1080
                    }
                };
                return callback(null, data);
            }
            data.previewInfo = {
                video:{
                    thumbs:["http://itbour-user.oss-cn-hangzhou.aliyuncs.com/images/U/2018/04/02/143351717_x6pktnDSHt"],
                    videoUrl : "http://itbour-user.oss-cn-hangzhou.aliyuncs.com/images/U/2018/04/02/143311367_ifimhA6KNQ",
                    duration : 100, videoSize : 241000, w:1920, h:1080
                }
            };
            return callback(null, data);
        });
        // 8. 按需重新获取预览信息
        tasks.push(function (data, callback) {
            if(Number(data.docInfo.generateStatus) !== 3 && !data.needRefresh) { // 不是生成成功, 且不需要获取预览信息
                return callback(null,data);
            }
            // 优先取高质量的视频资源 id
            var resId = data.docInfo.res_high ? data.docInfo.res_high : data.docInfo.res_mid;
            resId = resId ? resId : data.docInfo.res_low;
            var opt = {
                userId : options.userId,
                docId : data.docInfo.docId,
                resId : resId,
                bgId : data.docInfo.bgId
            };
            documentUtil.getUserVideoDocPreviewOnly(opt, function(preErr, previewInfo) {
                data.previewInfo = previewInfo;
                if (data.previewInfo && data.previewInfo.video) {
                    data.previewInfo.video.coverInfo = data.coverInfo;
                }
                return callback(preErr, data);
            });
        });
        // 9. 获取去水印价格信息
        tasks.push(function (data, callback) {
            var entity = new YjxPriceModel();
            entity.getWmPriceInfoForUserVideoDocWithDocId(data.docInfo.docId, function (error, priceInfo) {
                if(error || !priceInfo) {
                    return callback(error || '查询价格失败', data);
                }
                data.docInfo.watermarkPayType = priceInfo.pay_type;
                data.docInfo.watermarkFee = priceInfo.unit_price;
                data.docInfo.watermarkPts = priceInfo.unit_pts;
                return callback(error, data);
            });
        });
        async.waterfall(tasks, function (error, data) {
            if (data) {
                data.coverInfo = null;
            }
            return callback(error, data);
        });
    };

    /**
     * 设置视频作品生成状态为失败
     *
     * @author 王俊
     * @date 2018-04-12
     *
     * @param {Object} options 请求参数
     * @param {Number} options.uniDocId 作品统一标识
     * @param {Number} options.docId 作品子表 id
     * @param {Number} options.userId 用户 id
     * @param {Function} callback 回调函数
     */
    documentUtil.setVideoUserDocStateGenerateStatusFail = function (options, callback) {

        // 1. 更新 redis 生成失败
        VideoRenderLuadUtil.lua_video_set_state(options.docId, 2, function (setStateErr) {
            if(setStateErr) {
                console.log('documentUtil.setVideoUserDocStateGenerateStatusFail lua setErr: ' + setStateErr);
            }
            // 2. 更新 db 状态生成/失败
            var entity = new YjxVideoUserDocModel({
                doc_id : options.docId,
                state : 2,  /*生成失败*/
                del_flg : 0,
                update_by:options.userId
            });
            entity.updateToDB(function (error) {
                return callback(error);
            });
        });
    };

    /**
     * 仅获取作品预览信息
     *
     * @author 王俊
     * @date 2018-03-26
     *
     * @param {Object} options          参数
     * @param {Number} options.userId   用户唯一标识
     * @param {Number} options.docId    作品唯一标识
     * @param {Number} options.resId    视频资源 id
     * @param {Number} options.bgId     视频背景 id
     * @param callback  回调
     *          err:     获取预览失败
     *          data: {
     *              video: {
     *                  thumbs:
     *                  videoUrl:
     *                  duration:
     *                  videoSize:
     *                  w:
     *                  h:
     *              }
     *              currentBg: {
     *                  thumbs:
     *                  w:
     *                  h:
     *                  videoFrame: {
     *                      x:
     *                      y:
     *                      w:
     *                      h:
     *                  }
     *              }
     *          }
     */
    documentUtil.getUserVideoDocPreviewOnly = function (options, callback) {
        var tasks = [];
        // 1. 获取视频资源信息
        tasks.push(function (callback) {
            var entity = new YjxVideoResModel({
                res_id : options.resId,
                del_flg:0
            });
            entity.findFromDB(function (findErr, results) {
                if (findErr || !results || results.length <=0) {
                    return callback(findErr || '该视频尚未预览', null);
                }
                var videoRes = results[0];
                var data = {
                    video : {
                        thumbs : retUtil.safe_parser_JSON_string(videoRes.thumbs),
                        videoUrl : videoRes.url,
                        duration : videoRes.duration,
                        videoSize : videoRes.file_size,
                        w : videoRes.w,
                        h : videoRes.h
                    }
                };
                return callback(findErr, data);
            });
        });
        // 2. 按需获取背景信息
        tasks.push(function (data, callback) {
            if (!options.bgId || options.bgId <=0) {
                return callback(null, data);
            }
            documentUtil.getUserDesignDocPreview(options.userId, options.bgId, 0, function (error, bgInfo) {
                if(!error && bgInfo) {
                    data.currentBg = bgInfo.image;
                }
                return callback(error, data);
            });
        });

        // 3. 如果有背景, 获取背景坑位
        tasks.push(function (data, callback) {
            if(!options.bgId || options.bgId <=0) {
                return callback(null, data);
            }
            var entity = new YjxDesignUserDocModel({
                doc_id: options.bgId,
                user_id : options.userId,
                del_flg:0
            });
            // 获取视频坑位置
            entity.getViewBgContentVideoFrame(options.bgId, function (error, videoFrame) {
                data.currentBg.videoFrame = videoFrame;
                return callback(error, data);
            });
        });
        async.waterfall(tasks, function (error, data) {
            return callback(error, data);
        });

    };

    /**
     * 从数据库中获取用户作品基础信息
     *
     * @author 王俊
     * @date 2018-03-26
     *
     * @param {Object} options  参数
     * @param {Number} options.uniDocId     统一作品 id
     * @param {Number} options.userId     用户唯一标识
     * @param callback  回调
     *          err: 获取基础信息失败
     *          data: {
                   "id": 520,                   统一作品 id
                  "opType": 2,
                  "watermark": 1,
                  "watermarkPay": 0,
                  "formState": 0,
                  "showFormFb": 0,
                  "docId": 512,                 作品子表 id
                  "designId": 228,              作品对应模板 id
                  "generateStatus": 0,          生成状态
                  "docNm": "我的作品",
                  "createDay": "2018-02-24",
                  "designVip": 0
     *          }
     */
    documentUtil.getUserVideoDocBaseInfoFromDB = function (options, callback) {
        var tasks = [];
        // 1. 查询基本信息
        tasks.push(function (callback) {
            var uniDoc = new YjxUniUserDocModel();
            uniDoc.checkUniUserDocType(options.uniDocId, function (checkErr, typeInfo) {
                if(checkErr) {
                    return callback(checkErr, null);
                }
                var status = {};
                status.id = typeInfo.uni_doc_id;
                if(Number(typeInfo.doc_type) === 10) {      // 设计
                    status.opType = 1
                }
                if(Number(typeInfo.doc_type) === 20) {      // ppt
                    status.opType = 3
                }
                if(Number(typeInfo.doc_type) === 30) {      // 视频
                    status.opType = 2
                }
                status.watermark = typeInfo.watermark;
                status.watermarkPay = typeInfo.wm_paid;
                status.formState = Number(typeInfo.form_flg) === 1 ? 1 : 0;     // 表单状态, 1:使用表单(开启), 2:使用表单(关闭)
                status.showFormFb = Number(typeInfo.form_flg) === 0 ? 0 : 1;    // 是否显示表单反馈, 0 不显示, 1 显示, 开启过就显示
                status.docId = typeInfo.doc_id;
                status.designId = typeInfo.doc_design_id;
                status.bgId = typeInfo.video_bg_id;
                status.bgDesignId = typeInfo.bg_design_id;
                status.userId = typeInfo.user_id;
                return callback(checkErr, status)
            });
        });
        // 2. 获取作品基本信息
        tasks.push(function (data, callback) {
            var entity = new YjxVideoUserDocModel({
                doc_id : data.docId,
                del_flg : 0
            });
            entity.findFromDB(function (findErr, docs) {
                if (findErr || !docs || docs.length <=0) {
                    return callback(findErr || '该作品不存在或已删除', null);
                }
                var userDoc = docs[0];
                // 取 db 状态
                data.generateStatus = Number(userDoc.state);
                // 若 db 状态生成完成, 但是没有资源 id, 则强制指定状态为待生成
                if (data.generateStatus === 3 && userDoc.res_low <=0 && userDoc.res_mid <=0 && userDoc.res_high <=0) {
                    data.generateStatus = 0;
                }
                data.docNm = userDoc.doc_name;
                data.createDay = (new moment(userDoc.create_time)).format('YYYY-MM-DD');
                data.res_low = userDoc.res_low;
                data.comb_res_low = userDoc.comb_res_low;
                data.res_mid = userDoc.res_mid;
                data.comb_res_mid = userDoc.comb_res_mid;
                data.res_high = userDoc.res_high;
                data.comb_res_high = userDoc.comb_res_high;
                if (Number(userDoc.cover_dur) > 0) {
                    data.coverInfo = {
                        cover : userDoc.cover,
                        coverDuration : userDoc.cover_dur,
                        coverTime : userDoc.cover_time
                    };
                }
                return callback(findErr, data);
            });
        });
        // 4. 查询作品对应模板是否为 vip
        tasks.push(function (data, callback) {
            var entity = new VideoDesignDocModel({
                design_id : data.designId
            });
            entity.findFromDB(function (findErr, designs) {
                if(findErr || !designs || designs.length <=0) {
                    return callback(findErr || '该作品对应模板不存在或已删除', null);
                }
                data.designVip = designs[0].vip;
                data.designEntity = designs[0];
                return callback(findErr,data);
            });
        });
        async.waterfall(tasks, function (error, data) {
            if (!error && data) {
                var quality = data.watermarkPay ? 2 : 1;
                data.estimatedDuration = 0.5 * Number(data.designEntity.duration) * quality;
                delete  data.designEntity;
            }
            return callback(error, data);
        });
    };

    /**
     * 获取视频当前排版进度信息
     *
     * @author 王俊
     * @date 2018-03-26
     *
     * @param {Object} options
     * @param {Number} options.docId            作品标识
     * @param {Number} options.estimateDuration  默认预估时长
     * @param callback  回调
     *
     */
    documentUtil.getUserVideoDocProgressInfo = function (options, callback) {
        var tasks = [];

        // 1. 获取当前进度信息
        tasks.push(function (callback) {
            VideoRenderLuadUtil.lua_video_get_duration(options.docId, function (getProgressErr, progressInfo) {
                if (getProgressErr) {
                    return callback(getProgressErr, null);
                }
                var data = {};
                data.progress = progressInfo.progress || 0;
                data.currentDuration = progressInfo.duration || 0;
                data.estimatedDuration = progressInfo.estimate || options.estimateDuration || 0;

                console.log(JSON.stringify('VideoRenderLuadUtil.lua_video_get_duration: ' + progressInfo));
                return callback(getProgressErr, data);
            });
        });
        // 4. 计算下次请求时间
        tasks.push(function (data, callback) {
            var leftDuration = data.estimatedDuration - data.currentDuration;
            if (leftDuration > 0) {
                data.nextInterval = 0.5 * leftDuration;
            }
            if (leftDuration <= 0) {
                data.nextInterval = 1;
            }
            data.nextInterval = data.nextInterval < 1 ? 1 : data.nextInterval;
            data.nextInterval = data.nextInterval > 10 ? 10 : data.nextInterval;


            // 预估进度, 除第一次请求外, 均与 progress 保持一致
            data.estimatedProgress = data.progress < 10 ? 10 : data.progress;
            // 下次请求预估时间
            data.nextEstimated =(data.currentDuration + data.nextInterval ) / (data.estimatedDuration / 0.8) * 100;
            data.nextEstimated = isNaN(data.nextEstimated) ? 0 : data.nextEstimated;
            data.nextEstimated = data.nextEstimated <= data.progress ? data.progress + 10 : data.nextEstimated;
            data.nextEstimated = data.nextEstimated >= 90 ? 90 : data.nextEstimated;

            return callback(null, data);
        });

        async.waterfall(tasks, function (error, data) {
            return callback(error,data);
        });
    };

    /**
     * 获取自由创建的下载地址
     *
     * @param opt 参数对象
     * @param {Number} opt.userId      用户id
     * @param {Number} opt.docId     uni_doc_id 统一作品id
     * @param {Number} opt.bgId        背景id
     * @param {Number} opt.quality     标记获取哪种精度的视屏
     * @param {boolean} opt.withWm      水印标记
     * @param {Number} opt.downloadType  下载类型标记
     * @param callback 自由创建下载地址
     */
    documentUtil.getUserCustVideoDoc = function (opt,callback) {
        var tasks = [];
        tasks.push(function (callback) {
            var entity = new YjxCustVideoUserDocModel({
                uni_doc_id : opt.docId,
                user_id : opt.userId
            });
            entity.findFromDB(function (err,reslut) {
                if (err){ return callback(err, null);}
                var data = {};
                data.cusUserDocInfo = reslut;
                return callback(null,data);
            });
        });
        tasks.push(function (data,callback) {
            if (!data || !data.cusUserDocInfo){
                return callback("未获取到作品信息",null);
            }
            if (data.cusUserDocInfo[0].dirty === 0 && data.cusUserDocInfo[0].state === 3 &&  data.cusUserDocInfo[0].res_high > 0){
                return callback(null, data);
            }
            var option = {
                docId : data.cusUserDocInfo[0].doc_id ,
                quality : 3
            };
            rpcFunc.typesetCustomVideoUserDoc(option, function (error, result) {
                data.typesetResult = result;
                return callback(null, data);
            });
        });
        tasks.push(function (data,callback) {
            (new YjxCustVideoUserDocModel()).getCustUserVideoDocDowUrl(opt.userId,opt.docId,function (err,dowRes) {
                if (err){
                    return callback(err, null);
                }
                if (!dowRes || dowRes.length <= 0){
                    return callback("未获取到该资源下载地址",null);
                }else{
                    data.dowRes = dowRes;
                    return callback(null,data);
                }
            });
        });
        async.waterfall(tasks, function (error, data) {
            if (error || !data){
                return callback("未获取到该资源下载地址",null);
            }
            return callback(error,data.dowRes);
        });

    };



    /**
     * 创建自定义视频作品
     *
     * @author 王俊
     * @date 2018-07-04
     *
     * @param {Object} options
     * @param {Number} options.userId 用户唯一标识
     * @param {Number} options.uniDocId 用户作品唯一标识
     * @param {Number} options.sizeId 用户作品尺寸标识
     * @param {String} options.docString 用户作品文档数据 json 字符串
     * @param {String} [options.docName] 作品名称
     * @param {Function} callback 回调函数
     *                      error:
     *                      data: {
     *                          productId: 作品子表标识
     *                      }
     *
     */
    documentUtil.newCustomVideoDoc = function (options, callback) {
        var doc = retUtil.safe_parser_JSON_string(options.docString);
        if(!doc) return callback('文档格式有误', null);
        doc.docId = options.uniDocId;
        doc.opType = 4;

        var entity = new YjxCustVideoUserDocModel({
            uni_doc_id : options.uniDocId,
            doc_name : '' || '我的作品',
            user_id : options.userId,
            size_id : options.sizeId,
            purpose : 0,
            data : JSON.stringify(doc),
            duration: doc.duration,
            dirty: 1,
            state: 0,
            update_by: options.userId
        });
        entity.saveToDB(function (error, insertId) {
            return callback(error, {productId: insertId});
        });
    };

    /**
     * 创建自由创建视频作品
     *
     * @author 王俊
     * @date 2018-07-04
     *
     * @param {Object} options
     * @param {Number} options.device
     * @param {Number} options.userId
     * @param {String} options.docString
     * @param {Number} options.sizeId
     * @param {Function} callback
     *                      error:
     *                      data: {
     *                          docId:
     *                          productId:
     *                          opType: 4
     *                      }
     */
    documentUtil.newCustomVideoDoc_app_v3_0 = function (options, callback) {

        var totalTasks = [];
        // 1. 创建统一作品
        totalTasks.push(function (callback) {
            var opt = {
                userId : options.userId,
                opType : 4,     // 标记自由创建作品(无模板)
                watermark: 0,   // 自由创建作品无水印
            };
            documentUtil.newUniUserDoc(opt, function (error, uniDocInfo) {
                var data = {};
                data.uniDocInfo = uniDocInfo;
                return callback(error, data);
            });
        });
        // 2. 创建子作品
        totalTasks.push(function (data, callback) {
            var opt = {
                userId : options.userId,
                uniDocId : data.uniDocInfo.uniDocId,
                docString : options.docString,
                sizeId : options.sizeId
            };
            documentUtil.newCustomVideoDoc(opt, function (error, productInfo) {
                productInfo = productInfo || {};
                data.retData = {
                    docId : data.uniDocInfo.uniDocId,
                    productId : productInfo.productId
                };
                return callback(error, data);
            });
        });

        // 流式执行
        async.waterfall(totalTasks, function (error, data) {
            if(error) {
                return callback(error, null);
            }
            return callback(error, data.retData);
        });
    };

    /**
     * 更新用户自由创建作品
     *
     * @author 王俊
     * @date 2018-07-04
     *
     * @param {Object} options
     * @param {Number} [options.device]
     * @param {Number} options.uniDocId
     * @param {Number} options.userId
     * @param {String} options.docString
     * @param {Function} callback 回调函数
     *                      err:
     */
    documentUtil.updateCustomVideoDoc = function (options, callback) {

        var doc = retUtil.safe_parser_JSON_string(options.docString);
        if(!doc) return callback('文档格式有误', null);
        var entity = new YjxCustVideoUserDocModel();
        options.docString = JSON.stringify(options.docString); // 转成纯字符串
        entity.updateCustomVideoDocInfo(options, function (error, data) {
            return callback(error);
        });
    };

    /**
     * 获取自由创建用户作品信息
     *
     * @author 王俊
     * @date 2018-07-04
     *
     * @param {Object} options
     * @param {Object} options.device
     * @param {Object} options.userId
     * @param {Object} options.uniDocId
     * @param {Function} callback
     *                      error
     *                      data: {
     *                          docId:
     *                          productId:
     *                          opType
     *                          ...
     *                      }
     */
    documentUtil.getCustomVideoUserDocContent = function (options, callback) {

        var entity = new YjxCustVideoUserDocModel({
            uni_doc_id : options.uniDocId,
            user_id : options.userId,
            del_flg : 0
        });

        entity.findFromDB(function (error, docs) {
            if(error || !docs || docs.length <=0) {
                return callback(error || '该作品不存在或已删除', null);
            }
            var doc = docs[0];

            var retData = retUtil.safe_parser_JSON_string(doc.data);
            if(!retData) {
                return callback('该文档已损坏', null);
            }
            retData.docId = doc.uni_doc_id;
            retData.productId = doc.doc_id;
            retData.opType = 4;
            return callback(error, retData);
        });
    };

    /**
     * 获取用户自由创建作品预览信息, 未排版/排版失败则排版
     *
     * @author 王俊
     * @date 2018-07-04
     *
     * @param {Object} options
     * @param {Object} options.device
     * @param {Object} options.userId
     * @param {Object} options.uniDocId
     * @param {Function} callback
     *                      error
     *                      data: {
     *                           "id":4903,                  // 作品唯一标识
     *                           "opType":4,                 // 业务分类, 暂定如下: 1 竖屏(单页/印品等)  2 视频  3 PPT
     *                           "docNm":"欢度国庆",         // 作品名称
     *                           "createDay" : "2017-11-05", // 作品创建日期
     *                           "video":{                  // 当作品使用视频展示时返回此字段, 若作品需要使用图片展示时此字段为空
     *                               "thumbs":[              // 视频缩略图
     *                                 "http://itbour-generate.oss-cn-hangzhou.aliyuncs.com/image/U30330/2016/11/06/091954617_IqjCfwBAzWz7I683nMRf/0.jpg"
     *                               ],
     *                               "videoUrl" : "http://itbour-generate.oss-cn-hangzhou.aliyuncs.com/image/U30330/2016/11/06/091954617_IqjCfwBAzWz7I683nMRf/0.mp4",
     *                               "duration" : 100,       // 视频时长, 单位:秒
     *                               "videoSize" : 4093200,  // 视频文件大小, 单位: Byte, 前端计算使用1000做进制转换, 避免出现流量显示与使用不一致的情况
     *                               "w":720,
     *                               "h":1280,
     *                           }
     *                      }
     */
    documentUtil.getUserCustomVideoDocPreview = function (options, callback) {

        var totalTasks = [];

        // 1. 获取作品信息
        totalTasks.push(function (callback) {
            var entity = new YjxCustVideoUserDocModel({
                uni_doc_id : options.uniDocId,
                user_id : options.userId,
                del_flg : 0
            });
            entity.findFromDB(function (error, docs) {
                if(error || !docs || docs.length <=0 ) {
                    return callback(error || '该作品不存在或已删除', null);
                }
                var doc = docs[0];
                var data = {};
                data.docEntity = doc;
                // 作品有修改, 或状态没有生成成功
                if (data.docEntity.dirty || data.docEntity.state !== 3) {
                    data.needTypeset = true;
                }
                return callback(error, data);
            });
        });

        // 2. 按需排版
        totalTasks.push(function (data, callback) {
            if(!data.needTypeset) {
                return callback(null, data);
            }
            var opt = {
                docId : data.docEntity.doc_id,
                quality: 2,
            };
            rpcFunc.typesetCustomVideoUserDoc(opt, function (error, result) {
                data.typesetResult = result;
                return callback(error, data);
            })
        });

        // 3. 按需重新获取作品信息
        totalTasks.push(function (data, callback) {
            if(!data.needTypeset) {
                return callback(null, data);
            }
            var entity = new YjxCustVideoUserDocModel({
                uni_doc_id : options.uniDocId,
                user_id : options.userId,
                del_flg : 0
            });
            entity.findFromDB(function (error, docs) {
                if(error || !docs || docs.length <=0 ) {
                    return callback(error || '该作品不存在或已删除', null);
                }
                data.docEntity = docs[0];
                return callback(error, data);
            });
        });

        // 4. 获取视频资源信息
        totalTasks.push(function (data, callback) {
            var resId = data.docEntity.res_high;
            resId = resId ? resId : data.docEntity.res_mid;
            resId = resId ? resId : data.docEntity.res_low;

            var entity = new YjxVideoResModel({
                res_id : resId,
                del_flg : 0
            });
            entity.findFromDB(function (error, resources) {
                if(error || !resources || resources.length <=0) {
                    return callback(error || '预览失败', null);
                }
                var res = resources[0];
                // 构建返回值
                data.retData = {
                    id : data.docEntity.uni_doc_id,
                    opType: 4,
                    docNm : data.docEntity.doc_name,
                    createDay: (new moment(data.docEntity.create_time)).format('YYYY-MM-DD'),
                    video : {
                        thumbs : retUtil.safe_parser_JSON_string(data.docEntity.thumbs),
                        videoUrl: res.url,
                        duration: res.duration,
                        videoSize: res.file_size,
                        w: res.w,
                        h: res.h
                    }
                };
                return callback(error, data);
            });
        });

        // 流式执行
        async.waterfall(totalTasks, function (error, data) {
            if(error) return callback(error, null);
            return callback(error, data.retData);
        })


    };





    return documentUtil;
})();

module.exports = documentUtil;